1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 // gtest
17 #include <gtest/gtest.h>
18
19 #include <atomic>
20 #include <chrono>
21 #include <condition_variable>
22 #include <mutex>
23
24 #include <transaction/rs_transaction.h>
25 #include "display_manager.h"
26 #include "modifier_render_thread/rs_modifiers_draw_thread.h"
27 #include "rs_adapter.h"
28 #include "surface_draw.h"
29 #include "window_manager.h"
30 #include "window_test_utils.h"
31 #include "wm_common.h"
32
33 using namespace testing;
34 using namespace testing::ext;
35
36 namespace OHOS {
37 namespace Rosen {
38 namespace {
39 constexpr uint32_t COLOR_RED = 0xffff0000;
40 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowVisibilityInfoTest" };
41 constexpr uint8_t ALPHA = 255;
42 } // namespace
43
44 using Utils = WindowTestUtils;
45 constexpr int WAIT_ASYNC_MS_TIME_OUT = 5000; // 5000ms, filling color is slow
46
47 class VisibilityChangedListenerImpl : public IVisibilityChangedListener {
48 public:
VisibilityChangedListenerImpl(std::mutex & mutex,std::condition_variable & cv)49 VisibilityChangedListenerImpl(std::mutex& mutex, std::condition_variable& cv) : mutex_(mutex), cv_(cv) {}
50 void OnWindowVisibilityChanged(const std::vector<sptr<WindowVisibilityInfo>>& windowVisibilityInfo) override;
51 std::vector<sptr<WindowVisibilityInfo>> windowVisibilityInfos_;
52 bool isCallbackCalled_{ false };
53
54 private:
55 std::mutex& mutex_;
56 std::condition_variable& cv_;
57 };
58
OnWindowVisibilityChanged(const std::vector<sptr<WindowVisibilityInfo>> & windowVisibilityInfo)59 void VisibilityChangedListenerImpl::OnWindowVisibilityChanged(
60 const std::vector<sptr<WindowVisibilityInfo>>& windowVisibilityInfo)
61 {
62 std::unique_lock<std::mutex> lock(mutex_);
63 WLOGI("size:%{public}zu", windowVisibilityInfo.size());
64 windowVisibilityInfos_ = std::move(windowVisibilityInfo);
65 for (auto& info : windowVisibilityInfos_) {
66 WLOGI("windowId:%{public}u, visibleState:%{public}d, pid:%{public}d, uid:%{public}d, windowType:%{public}u",
67 info->windowId_,
68 static_cast<uint32_t>(info->visibilityState_),
69 info->pid_,
70 info->uid_,
71 static_cast<uint32_t>(info->windowType_));
72 }
73 isCallbackCalled_ = true;
74 cv_.notify_all();
75 }
76
77 class WindowVisibilityInfoTest : public testing::Test {
78 public:
79 static void SetUpTestCase();
80
81 static void TearDownTestCase();
82
83 virtual void SetUp() override;
84
85 virtual void TearDown() override;
86
87 static inline std::mutex mutex_;
88 static inline std::condition_variable cv_;
89 static inline sptr<VisibilityChangedListenerImpl> visibilityChangedListener_ =
90 new VisibilityChangedListenerImpl(mutex_, cv_);
91
ResetCallbackCalledFLag()92 static inline void ResetCallbackCalledFLag()
93 {
94 std::unique_lock<std::mutex> lock(mutex_);
95 visibilityChangedListener_->isCallbackCalled_ = false;
96 visibilityChangedListener_->windowVisibilityInfos_.clear();
97 }
98
99 static void WaitForCallback();
100 Utils::TestWindowInfo fullScreenAppInfo_;
101 Utils::TestWindowInfo floatAppInfo_;
102 Utils::TestWindowInfo subAppInfo_;
103 bool FillColor(sptr<Window> window);
104 };
105
FillColor(sptr<Window> window)106 bool WindowVisibilityInfoTest::FillColor(sptr<Window> window)
107 {
108 if (window == nullptr) {
109 return false;
110 }
111 auto surfaceNode = window->GetSurfaceNode();
112 if (surfaceNode == nullptr) {
113 return false;
114 }
115 Rect rect = window->GetRect();
116 bool isDrawSuccess = SurfaceDraw::DrawColor(surfaceNode, rect.width_, rect.height_, COLOR_RED);
117 surfaceNode->SetAbilityBGAlpha(ALPHA);
118 RSTransactionAdapter::FlushImplicitTransaction(surfaceNode);
119 return isDrawSuccess;
120 }
121
SetUpTestCase()122 void WindowVisibilityInfoTest::SetUpTestCase()
123 {
124 auto display = DisplayManager::GetInstance().GetDisplayById(0);
125 ASSERT_TRUE((display != nullptr));
126 WLOGI("GetDefaultDisplay: id %{public}" PRIu64 ", w %{public}d, h %{public}d, fps %{public}u",
127 display->GetId(),
128 display->GetWidth(),
129 display->GetHeight(),
130 display->GetRefreshRate());
131 Rect displayRect = {
132 0, 0, static_cast<uint32_t>(display->GetWidth()), static_cast<uint32_t>(display->GetHeight())
133 };
134 Utils::InitByDisplayRect(displayRect);
135 WindowManager::GetInstance().RegisterVisibilityChangedListener(visibilityChangedListener_);
136 auto displayId = DisplayManager::GetInstance().GetDefaultDisplayId();
137 WindowManager::GetInstance().MinimizeAllAppWindows(displayId);
138 }
139
TearDownTestCase()140 void WindowVisibilityInfoTest::TearDownTestCase()
141 {
142 WindowManager::GetInstance().UnregisterVisibilityChangedListener(visibilityChangedListener_);
143 #ifdef RS_ENABLE_VK
144 RSModifiersDrawThread::Destroy();
145 #endif
146 }
147
SetUp()148 void WindowVisibilityInfoTest::SetUp()
149 {
150 fullScreenAppInfo_ = {
151 .name = "FullWindow",
152 .rect = Utils::customAppRect_,
153 .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW,
154 .mode = WindowMode::WINDOW_MODE_FULLSCREEN,
155 .needAvoid = false,
156 .parentLimit = false,
157 .showWhenLocked = true,
158 .parentId = INVALID_WINDOW_ID,
159 };
160 floatAppInfo_ = {
161 .name = "ParentWindow",
162 .rect = Utils::customAppRect_,
163 .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW,
164 .mode = WindowMode::WINDOW_MODE_FLOATING,
165 .needAvoid = false,
166 .parentLimit = false,
167 .showWhenLocked = true,
168 .parentId = INVALID_WINDOW_ID,
169 };
170 subAppInfo_ = {
171 .name = "SubWindow",
172 .rect = Utils::customAppRect_,
173 .type = WindowType::WINDOW_TYPE_APP_SUB_WINDOW,
174 .mode = WindowMode::WINDOW_MODE_FLOATING,
175 .needAvoid = false,
176 .parentLimit = false,
177 .showWhenLocked = true,
178 .parentId = INVALID_WINDOW_ID,
179 };
180 }
181
TearDown()182 void WindowVisibilityInfoTest::TearDown() {}
183
WaitForCallback()184 void WindowVisibilityInfoTest::WaitForCallback()
185 {
186 std::unique_lock<std::mutex> lock(mutex_);
187 visibilityChangedListener_->isCallbackCalled_ = false;
188 visibilityChangedListener_->windowVisibilityInfos_.clear();
189 auto now = std::chrono::system_clock::now();
190 if (!cv_.wait_until(lock, now + std::chrono::milliseconds(WAIT_ASYNC_MS_TIME_OUT), []() {
191 return visibilityChangedListener_->isCallbackCalled_;
192 })) {
193 WLOGI("wait_until time out");
194 }
195 }
196
197 namespace {
198 /**
199 * @tc.name: WindowVisibilityInfoTest01
200 * @tc.desc: window show or hide
201 * @tc.type: FUNC
202 * @tc.require: issueI5FSQW
203 */
204 HWTEST_F(WindowVisibilityInfoTest, WindowVisibilityInfoTest01, TestSize.Level1)
205 {
206 floatAppInfo_.name = "window1";
207 floatAppInfo_.rect = { 0, 0, 300, 100 };
208 sptr<Window> window1 = Utils::CreateTestWindow(floatAppInfo_);
209 if (window1 == nullptr) {
210 return;
211 }
212
213 subAppInfo_.name = "subWindow1";
214 subAppInfo_.rect = { 0, 600, 300, 100 };
215 subAppInfo_.parentId = window1->GetWindowId();
216 sptr<Window> subWindow1 = Utils::CreateTestWindow(subAppInfo_);
217 ASSERT_NE(nullptr, subWindow1);
218 bool isWindowVisible = false;
219 bool isSubWindowVisible = false;
220
221 [[maybe_unused]] uint32_t visibilityInfoCount = 0;
222 ASSERT_EQ(WMError::WM_OK, window1->Show());
223 isWindowVisible = FillColor(window1);
224 WaitForCallback();
225 visibilityInfoCount = isWindowVisible ? 1 : 0;
226 ResetCallbackCalledFLag();
227
228 ASSERT_EQ(WMError::WM_OK, subWindow1->Show());
229 isSubWindowVisible = FillColor(subWindow1);
230 WaitForCallback();
231 visibilityInfoCount = isSubWindowVisible ? 1 : 0;
232 ResetCallbackCalledFLag();
233
234 ASSERT_EQ(WMError::WM_OK, subWindow1->Hide());
235 WaitForCallback();
236 visibilityInfoCount = isSubWindowVisible ? 1 : 0;
237 ResetCallbackCalledFLag();
238
239 ASSERT_EQ(WMError::WM_OK, window1->Hide());
240 WaitForCallback();
241 visibilityInfoCount = isWindowVisible ? 1 : 0;
242 ResetCallbackCalledFLag();
243
244 window1->Destroy();
245 subWindow1->Destroy();
246 sleep(2);
247 }
248 } // namespace
249 } // namespace Rosen
250 } // namespace OHOS
251