!1045 适配窗口可见性计算逻辑从WMS移动到RS

Merge pull request !1045 from 王良江/br_window_kejian_test
This commit is contained in:
openharmony_ci
2022-06-25 07:48:27 +00:00
committed by Gitee
10 changed files with 194 additions and 63 deletions
@@ -36,7 +36,7 @@ namespace {
}
using utils = WindowTestUtils;
constexpr int WAIT_ASYNC_MS_TIME_OUT = 1500; // 1500ms
constexpr int WAIT_ASYNC_MS_TIME_OUT = 2000; // 2000ms
#define CHECK_DISPLAY_POWER_STATE_RETURN() \
do { \
@@ -327,6 +327,49 @@ end:
window2->Destroy();
subWindow2->Destroy();
}
/**
* @tc.name: WindowVisibilityInfoTest04
* @tc.desc: add two main window and sub windows and test callback
* @tc.type: FUNC
*/
HWTEST_F(WindowVisibilityInfoTest, WindowVisibilityInfoTest04, Function | MediumTest | Level1)
{
floatAppInfo_.name = "window1";
floatAppInfo_.rect = {0, 0, 300, 600};
sptr<Window> window1 = utils::CreateTestWindow(floatAppInfo_);
floatAppInfo_.name = "window2";
floatAppInfo_.rect = {0, 0, 300, 300};
sptr<Window> window2 = utils::CreateTestWindow(floatAppInfo_);
floatAppInfo_.name = "window3";
floatAppInfo_.rect = {0, 300, 300, 300};
sptr<Window> window3 = utils::CreateTestWindow(floatAppInfo_);
ASSERT_EQ(WMError::WM_OK, window1->Show());
WaitForCallback();
CHECK_DISPLAY_POWER_STATE_RETURN();
ASSERT_EQ(1, visibilityChangedListener_->windowVisibilityInfos_.size());
ResetCallbackCalledFLag();
ASSERT_EQ(WMError::WM_OK, window2->Show());
WaitForCallback();
CHECK_DISPLAY_POWER_STATE_RETURN();
ASSERT_EQ(1, visibilityChangedListener_->windowVisibilityInfos_.size());
ResetCallbackCalledFLag();
ASSERT_EQ(WMError::WM_OK, window3->Show());
WaitForCallback();
CHECK_DISPLAY_POWER_STATE_RETURN();
ASSERT_EQ(2, visibilityChangedListener_->windowVisibilityInfos_.size());
ResetCallbackCalledFLag();
end:
window1->Destroy();
window2->Destroy();
window3->Destroy();
}
}
} // namespace Rosen
} // namespace OHOS
@@ -23,6 +23,7 @@
#include <nocopyable.h>
#include <system_ability.h>
#include <window_manager_service_handler_stub.h>
#include <transaction/rs_interfaces.h>
#include "display_change_listener.h"
#include "drag_controller.h"
#include "freeze_controller.h"
@@ -110,6 +111,8 @@ private:
bool Init();
void RegisterSnapshotHandler();
void RegisterWindowManagerServiceHandler();
void RegisterWindowVisibilityChangeCallback();
void WindowVisibilityChangeCallback(std::shared_ptr<RSOcclusionData> occlusionData);
void OnWindowEvent(Event event, const sptr<IRemoteObject>& remoteObject);
void NotifyDisplayStateChange(DisplayId defaultDisplayId, sptr<DisplayInfo> displayInfo,
const std::map<DisplayId, sptr<DisplayInfo>>& displayInfoMap, DisplayStateChangeType type);
@@ -130,6 +133,7 @@ private:
SystemConfig systemConfig_;
ModeChangeHotZonesConfig hotZonesConfig_ { false, 0, 0, 0 };
std::unique_ptr<WindowTaskLooper> wmsTaskLooper_;
RSInterfaces& rsInterface_;
bool startingOpen_ = true;
};
}
+1 -1
View File
@@ -116,7 +116,7 @@ public:
int32_t priority_ { 0 };
bool requestedVisibility_ { false };
bool currentVisibility_ { false };
bool isCovered_ { true }; // initial value true to ensure notification when this window is shown
bool isVisible_ { false };
bool isAppCrash_ { false };
bool isPlayAnimationShow_ { false };
bool isPlayAnimationHide_ { false };
-2
View File
@@ -131,8 +131,6 @@ private:
bool TraverseFromTopToBottom(sptr<WindowNode> node, const WindowNodeOperationFunc& func) const;
bool TraverseFromBottomToTop(sptr<WindowNode> node, const WindowNodeOperationFunc& func) const;
void RecoverScreenDefaultOrientationIfNeed(DisplayId displayId);
// cannot determine in case of a window covered by union of several windows or with transparent value
void UpdateWindowVisibilityInfos(std::vector<sptr<WindowVisibilityInfo>>& infos);
void RaiseOrderedWindowToTop(std::vector<sptr<WindowNode>>& orderedNodes,
std::vector<sptr<WindowNode>>& windowNodes);
static bool ReadIsWindowAnimationEnabledProperty();
+7
View File
@@ -17,6 +17,7 @@
#include <refbase.h>
#include <iremote_object.h>
#include <transaction/rs_interfaces.h>
#include "agent_death_recipient.h"
#include "display_manager_service_inner.h"
@@ -51,6 +52,8 @@ public:
bool IsForbidDockSliceMove(DisplayId displayId) const;
bool IsDockSliceInExitSplitModeArea(DisplayId displayId) const;
void ExitSplitMode(DisplayId displayId);
void NotifyWindowVisibilityChange(std::shared_ptr<RSOcclusionData> occlusionData);
void AddSurfaceNodeIdWindowNodePair(uint64_t surfaceNodeId, sptr<WindowNode> node);
WMError RequestFocus(uint32_t windowId);
WMError RequestActiveWindow(uint32_t windowId);
@@ -113,8 +116,12 @@ private:
void MoveNotShowingWindowToDefaultDisplay(DisplayId defaultDisplayId, DisplayId displayId);
WMError PostProcessAddWindowNode(sptr<WindowNode>& node, sptr<WindowNode>& parentNode,
sptr<WindowNodeContainer>& container);
std::vector<std::pair<uint64_t, bool>> GetWindowVisibilityChangeInfo(
std::shared_ptr<RSOcclusionData> occlusionData);
std::map<uint32_t, sptr<WindowNode>> windowNodeMap_;
std::map<sptr<IRemoteObject>, uint32_t> windowIdMap_;
std::map<uint64_t, sptr<WindowNode>> surfaceIdWindowNodeMap_;
std::shared_ptr<RSOcclusionData> lastOcclusionData_ = std::make_shared<RSOcclusionData>();
std::map<ScreenId, sptr<WindowNodeContainer>> windowNodeContainerMap_;
std::map<ScreenId, std::vector<DisplayId>> displayIdMap_;
+1
View File
@@ -170,6 +170,7 @@ WMError WindowController::CreateWindow(sptr<IWindow>& window, sptr<WindowPropert
if (node != nullptr && WindowHelper::IsMainWindow(property->GetWindowType()) && node->startingWindowShown_) {
StartingWindow::HandleClientWindowCreate(node, window, windowId, surfaceNode, property, pid, uid);
windowRoot_->AddDeathRecipient(node);
windowRoot_->AddSurfaceNodeIdWindowNodePair(surfaceNode->GetId(), node);
return WMError::WM_OK;
}
windowId = GenWindowId();
+2
View File
@@ -166,6 +166,7 @@ WMError WindowDumper::DumpSpecifiedWindowInfo(uint32_t windowId, const std::vect
}
Rect rect = node->GetWindowRect();
std::string isShown_ = node->startingWindowShown_ ? "true" : "false";
std::string isVisible = node->isVisible_ ? "true" : "false";
std::ostringstream oss;
oss << "WindowName: " << node->GetWindowName() << std::endl;
oss << "DisplayId: " << node->GetDisplayId() << std::endl;
@@ -176,6 +177,7 @@ WMError WindowDumper::DumpSpecifiedWindowInfo(uint32_t windowId, const std::vect
oss << "Flag: " << node->GetWindowFlags() << std::endl;
oss << "Orientation: " << static_cast<uint32_t>(node->GetRequestedOrientation()) << std::endl;
oss << "IsStartingWindow: " << isShown_ << std::endl;
oss << "IsVisible: " << isVisible << std::endl;
oss << "WindowRect: " << "[ "
<< rect.posX_ << ", " << rect.posY_ << ", " << rect.width_ << ", " << rect.height_
<< " ]" << std::endl;
+46 -1
View File
@@ -46,7 +46,8 @@ WM_IMPLEMENT_SINGLE_INSTANCE(WindowManagerService)
const bool REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(&SingletonContainer::Get<WindowManagerService>());
WindowManagerService::WindowManagerService() : SystemAbility(WINDOW_MANAGER_SERVICE_ID, true)
WindowManagerService::WindowManagerService() : SystemAbility(WINDOW_MANAGER_SERVICE_ID, true),
rsInterface_(RSInterfaces::GetInstance())
{
windowRoot_ = new WindowRoot(
std::bind(&WindowManagerService::OnWindowEvent, this, std::placeholders::_1, std::placeholders::_2));
@@ -71,9 +72,53 @@ void WindowManagerService::OnStart()
DisplayManagerServiceInner::GetInstance().RegisterDisplayChangeListener(listener);
RegisterSnapshotHandler();
RegisterWindowManagerServiceHandler();
RegisterWindowVisibilityChangeCallback();
wmsTaskLooper_->Start();
}
void WindowManagerService::WindowVisibilityChangeCallback(std::shared_ptr<RSOcclusionData> occlusionData)
{
WLOGFD("NotifyWindowVisibilityChange: enter");
std::weak_ptr<RSOcclusionData> weak(occlusionData);
return wmsTaskLooper_->ScheduleTask([this, weak]() {
auto weakOcclusionData = weak.lock();
if (weakOcclusionData == nullptr) {
WLOGFE("weak occlusionData is nullptr");
return;
}
windowRoot_->NotifyWindowVisibilityChange(weakOcclusionData);
}).wait();
}
void WindowManagerService::RegisterWindowVisibilityChangeCallback()
{
auto windowVisibilityChangeCb = std::bind(&WindowManagerService::WindowVisibilityChangeCallback, this,
std::placeholders::_1);
if (rsInterface_.RegisterOcclusionChangeCallback(windowVisibilityChangeCb) != WM_OK) {
WLOGFW("WindowManagerService::RegisterWindowVisibilityChangeCallback failed, create async thread!");
auto fun = [this, windowVisibilityChangeCb]() {
WLOGFI("WindowManagerService::RegisterWindowVisibilityChangeCallback async thread enter!");
int counter = 0;
while (rsInterface_.RegisterOcclusionChangeCallback(windowVisibilityChangeCb) != WM_OK) {
usleep(10000); // 10000us equals to 10ms
counter++;
if (counter >= 2000) { // wait for 2000 * 10ms = 20s
WLOGFE("WindowManagerService::RegisterWindowVisibilityChangeCallback timeout!");
return;
}
}
WLOGFI("WindowManagerService::RegisterWindowVisibilityChangeCallback async thread register handler"
" successfully!");
};
std::thread thread(fun);
thread.detach();
WLOGFI("WindowManagerService::RegisterWindowVisibilityChangeCallback async thread has been detached!");
} else {
WLOGFI("WindowManagerService::RegisterWindowVisibilityChangeCallback OnStart succeed!");
}
}
void WindowManagerService::RegisterSnapshotHandler()
{
if (snapshotController_ == nullptr) {
-58
View File
@@ -179,8 +179,6 @@ WMError WindowNodeContainer::AddWindowNode(sptr<WindowNode>& node, sptr<WindowNo
AssignZOrder();
layoutPolicy_->AddWindowNode(node);
NotifyIfAvoidAreaChanged(node, AvoidControlType::AVOID_NODE_ADD);
std::vector<sptr<WindowVisibilityInfo>> infos;
UpdateWindowVisibilityInfos(infos);
DumpScreenWindowTree();
NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_ADDED);
UpdateCameraFloatWindowStatus(node, true);
@@ -269,17 +267,6 @@ WMError WindowNodeContainer::RemoveWindowNode(sptr<WindowNode>& node)
node->requestedVisibility_ = false;
node->currentVisibility_ = false;
node->isCovered_ = true;
std::vector<sptr<WindowVisibilityInfo>> infos = {new WindowVisibilityInfo(node->GetWindowId(),
node->GetCallingPid(), node->GetCallingUid(), false, node->GetWindowType())};
for (auto& child : node->children_) {
if (child->currentVisibility_) {
child->currentVisibility_ = false;
child->isCovered_ = true;
infos.emplace_back(new WindowVisibilityInfo(child->GetWindowId(), child->GetCallingPid(),
child->GetCallingUid(), false, child->GetWindowType()));
}
}
// Remove node from RSTree
for (auto& displayId : node->GetShowingDisplays()) {
UpdateRSTree(node, displayId, false, node->isPlayAnimationHide_);
@@ -298,7 +285,6 @@ WMError WindowNodeContainer::RemoveWindowNode(sptr<WindowNode>& node)
NotifyDockWindowStateChanged(node, true);
}
NotifyIfAvoidAreaChanged(node, AvoidControlType::AVOID_NODE_REMOVE);
UpdateWindowVisibilityInfos(infos);
DumpScreenWindowTree();
NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_REMOVED);
RecoverScreenDefaultOrientationIfNeed(node->GetDisplayId());
@@ -1700,50 +1686,6 @@ bool WindowNodeContainer::TraverseFromBottomToTop(sptr<WindowNode> node, const W
return false;
}
void WindowNodeContainer::UpdateWindowVisibilityInfos(std::vector<sptr<WindowVisibilityInfo>>& infos)
{
// clear vector cache completely, swap with empty vector
auto emptyVector = std::vector<Rect>();
currentCoveredArea_.swap(emptyVector);
WindowNodeOperationFunc func = [this, &infos](sptr<WindowNode> node) {
if (node == nullptr) {
return false;
}
Rect layoutRect = node->GetWindowRect();
const Rect& displayRect = displayGroupInfo_->GetDisplayRect(node->GetDisplayId());
int32_t nodeX = std::max(0, layoutRect.posX_);
int32_t nodeY = std::max(0, layoutRect.posY_);
int32_t nodeXEnd = std::min(displayRect.posX_ + static_cast<int32_t>(displayRect.width_),
layoutRect.posX_ + static_cast<int32_t>(layoutRect.width_));
int32_t nodeYEnd = std::min(displayRect.posY_ + static_cast<int32_t>(displayRect.height_),
layoutRect.posY_ + static_cast<int32_t>(layoutRect.height_));
Rect rectInDisplay = {nodeX, nodeY,
static_cast<uint32_t>(nodeXEnd - nodeX), static_cast<uint32_t>(nodeYEnd - nodeY)};
bool isCovered = false;
for (auto& rect : currentCoveredArea_) {
if (rectInDisplay.IsInsideOf(rect)) {
isCovered = true;
WLOGD("UpdateWindowVisibilityInfos: find covered window:%{public}u", node->GetWindowId());
break;
}
}
if (!isCovered) {
currentCoveredArea_.emplace_back(rectInDisplay);
}
if (isCovered != node->isCovered_) {
node->isCovered_ = isCovered;
infos.emplace_back(new WindowVisibilityInfo(node->GetWindowId(), node->GetCallingPid(),
node->GetCallingUid(), !isCovered, node->GetWindowType()));
WLOGD("UpdateWindowVisibilityInfos: covered status changed window:%{public}u, covered:%{public}d",
node->GetWindowId(), isCovered);
}
return false;
};
TraverseWindowTree(func, true);
WindowManagerAgentController::GetInstance().UpdateWindowVisibilityInfo(infos);
}
float WindowNodeContainer::GetVirtualPixelRatio(DisplayId displayId) const
{
return layoutPolicy_->GetVirtualPixelRatio(displayId);
+89
View File
@@ -24,6 +24,7 @@
#include "window_manager_hilog.h"
#include "window_manager_service.h"
#include "wm_trace.h"
#include "window_manager_agent_controller.h"
namespace OHOS {
namespace Rosen {
@@ -181,6 +182,9 @@ WMError WindowRoot::SaveWindow(const sptr<WindowNode>& node)
WLOGFI("save windowId %{public}u", node->GetWindowId());
windowNodeMap_.insert(std::make_pair(node->GetWindowId(), node));
if (node->surfaceNode_ != nullptr) {
surfaceIdWindowNodeMap_.insert(std::make_pair(node->surfaceNode_->GetId(), node));
}
if (node->GetWindowToken()) {
AddDeathRecipient(node);
}
@@ -256,6 +260,69 @@ void WindowRoot::ExitSplitMode(DisplayId displayId)
container->ExitSplitMode(displayId);
}
void WindowRoot::AddSurfaceNodeIdWindowNodePair(uint64_t surfaceNodeId, sptr<WindowNode> node)
{
surfaceIdWindowNodeMap_.insert(std::make_pair(surfaceNodeId, node));
}
std::vector<std::pair<uint64_t, bool>> WindowRoot::GetWindowVisibilityChangeInfo(
std::shared_ptr<RSOcclusionData> occlusionData)
{
std::vector<std::pair<uint64_t, bool>> visibityChangeInfo;
VisibleData& currentVisibleWindow = occlusionData->GetVisibleData();
std::sort(currentVisibleWindow.begin(), currentVisibleWindow.end());
VisibleData& lastVisibleWindow = lastOcclusionData_->GetVisibleData();
uint32_t i, j;
i = j = 0;
for (; i < lastVisibleWindow.size() && j < currentVisibleWindow.size();) {
if (lastVisibleWindow[i] < currentVisibleWindow[j]) {
visibityChangeInfo.push_back(std::make_pair(lastVisibleWindow[i], false));
i++;
} else if (lastVisibleWindow[i] > currentVisibleWindow[j]) {
visibityChangeInfo.push_back(std::make_pair(currentVisibleWindow[j], true));
j++;
} else {
i++;
j++;
}
}
for (; i < lastVisibleWindow.size(); ++i) {
visibityChangeInfo.push_back(std::make_pair(lastVisibleWindow[i], false));
}
for (; j < currentVisibleWindow.size(); ++j) {
visibityChangeInfo.push_back(std::make_pair(currentVisibleWindow[j], true));
}
lastOcclusionData_ = occlusionData;
return visibityChangeInfo;
}
void WindowRoot::NotifyWindowVisibilityChange(std::shared_ptr<RSOcclusionData> occlusionData)
{
std::vector<std::pair<uint64_t, bool>> visibityChangeInfo = GetWindowVisibilityChangeInfo(occlusionData);
std::vector<sptr<WindowVisibilityInfo>> windowVisibilityInfos;
for (const auto& elem : visibityChangeInfo) {
uint64_t surfaceId = elem.first;
bool isVisible = elem.second;
auto iter = surfaceIdWindowNodeMap_.find(surfaceId);
if (iter == surfaceIdWindowNodeMap_.end()) {
continue;
}
sptr<WindowNode> node = iter->second;
if (node == nullptr) {
continue;
}
node->isVisible_ = isVisible;
windowVisibilityInfos.emplace_back(new WindowVisibilityInfo(node->GetWindowId(), node->GetCallingPid(),
node->GetCallingUid(), isVisible, node->GetWindowType()));
WLOGFD("NotifyWindowVisibilityChange: covered status changed window:%{public}u, isVisible:%{public}d",
node->GetWindowId(), isVisible);
}
if (windowVisibilityInfos.size() != 0) {
WindowManagerAgentController::GetInstance().UpdateWindowVisibilityInfo(windowVisibilityInfos);
}
}
std::vector<Rect> WindowRoot::GetAvoidAreaByType(uint32_t windowId, AvoidAreaType avoidAreaType)
{
std::vector<Rect> avoidArea;
@@ -612,6 +679,28 @@ WMError WindowRoot::DestroyWindowInner(sptr<WindowNode>& node)
return WMError::WM_ERROR_DESTROYED_OBJECT;
}
std::vector<sptr<WindowVisibilityInfo>> windowVisibilityInfos;
node->isVisible_ = false;
windowVisibilityInfos.emplace_back(new WindowVisibilityInfo(node->GetWindowId(), node->GetCallingPid(),
node->GetCallingUid(), false, node->GetWindowType()));
WLOGFD("NotifyWindowVisibilityChange: covered status changed window:%{public}u, isVisible:%{public}d",
node->GetWindowId(), node->isVisible_);
WindowManagerAgentController::GetInstance().UpdateWindowVisibilityInfo(windowVisibilityInfos);
auto cmpFunc = [node](const std::map<uint64_t, sptr<WindowNode>>::value_type& pair) {
if (pair.second == nullptr) {
return false;
}
if (pair.second->GetWindowId() == node->GetWindowId()) {
return true;
}
return false;
};
auto iter = std::find_if(surfaceIdWindowNodeMap_.begin(), surfaceIdWindowNodeMap_.end(), cmpFunc);
if (iter != surfaceIdWindowNodeMap_.end()) {
surfaceIdWindowNodeMap_.erase(iter);
}
sptr<IWindow> window = node->GetWindowToken();
if ((window != nullptr) && (window->AsObject() != nullptr)) {
if (windowIdMap_.count(window->AsObject()) == 0) {