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 "surface_draw.h"
27 #include "window_manager.h"
28 #include "window_test_utils.h"
29 #include "wm_common.h"
30
31 using namespace testing;
32 using namespace testing::ext;
33
34 namespace OHOS {
35 namespace Rosen {
36 namespace {
37 constexpr uint32_t COLOR_RED = 0xffff0000;
38 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowVisibilityInfoTest"};
39 constexpr uint8_t ALPHA = 255;
40 }
41
42 using Utils = WindowTestUtils;
43 constexpr int WAIT_ASYNC_MS_TIME_OUT = 5000; // 5000ms, filling color is slow
44
45 class VisibilityChangedListenerImpl : public IVisibilityChangedListener {
46 public:
VisibilityChangedListenerImpl(std::mutex & mutex,std::condition_variable & cv)47 VisibilityChangedListenerImpl(std::mutex& mutex, std::condition_variable& cv) : mutex_(mutex), cv_(cv) {}
48 void OnWindowVisibilityChanged(const std::vector<sptr<WindowVisibilityInfo>>& windowVisibilityInfo) override;
49 std::vector<sptr<WindowVisibilityInfo>> windowVisibilityInfos_;
50 bool isCallbackCalled_ { false };
51 private:
52 std::mutex& mutex_;
53 std::condition_variable& cv_;
54 };
55
OnWindowVisibilityChanged(const std::vector<sptr<WindowVisibilityInfo>> & windowVisibilityInfo)56 void VisibilityChangedListenerImpl::OnWindowVisibilityChanged(
57 const std::vector<sptr<WindowVisibilityInfo>>& windowVisibilityInfo)
58 {
59 std::unique_lock<std::mutex> lock(mutex_);
60 WLOGI("size:%{public}zu", windowVisibilityInfo.size());
61 windowVisibilityInfos_ = std::move(windowVisibilityInfo);
62 for (auto& info : windowVisibilityInfos_) {
63 WLOGI("windowId:%{public}u, visibleState:%{public}d, pid:%{public}d, uid:%{public}d, windowType:%{public}u",
64 info->windowId_, static_cast<uint32_t>(info->visibilityState_), info->pid_, info->uid_,
65 static_cast<uint32_t>(info->windowType_));
66 }
67 isCallbackCalled_ = true;
68 cv_.notify_all();
69 }
70
71 class WindowVisibilityInfoTest : public testing::Test {
72 public:
73 static void SetUpTestCase();
74
75 static void TearDownTestCase();
76
77 virtual void SetUp() override;
78
79 virtual void TearDown() override;
80
81 static inline std::mutex mutex_;
82 static inline std::condition_variable cv_;
83 static inline sptr<VisibilityChangedListenerImpl> visibilityChangedListener_ =
84 new VisibilityChangedListenerImpl(mutex_, cv_);
85
ResetCallbackCalledFLag()86 static inline void ResetCallbackCalledFLag()
87 {
88 std::unique_lock<std::mutex> lock(mutex_);
89 visibilityChangedListener_->isCallbackCalled_ = false;
90 visibilityChangedListener_->windowVisibilityInfos_.clear();
91 }
92
93 static void WaitForCallback();
94 Utils::TestWindowInfo fullScreenAppInfo_;
95 Utils::TestWindowInfo floatAppInfo_;
96 Utils::TestWindowInfo subAppInfo_;
97 bool FillColor(sptr<Window> window);
98 };
99
FillColor(sptr<Window> window)100 bool WindowVisibilityInfoTest::FillColor(sptr<Window> window)
101 {
102 if (window == nullptr) {
103 return false;
104 }
105 auto surfaceNode = window->GetSurfaceNode();
106 if (surfaceNode == nullptr) {
107 return false;
108 }
109 Rect rect = window->GetRect();
110 bool isDrawSuccess = SurfaceDraw::DrawColor(surfaceNode, rect.width_, rect.height_, COLOR_RED);
111 surfaceNode->SetAbilityBGAlpha(ALPHA);
112 RSTransaction::FlushImplicitTransaction();
113 return isDrawSuccess;
114 }
115
SetUpTestCase()116 void WindowVisibilityInfoTest::SetUpTestCase()
117 {
118 auto display = DisplayManager::GetInstance().GetDisplayById(0);
119 ASSERT_TRUE((display != nullptr));
120 WLOGI("GetDefaultDisplay: id %{public}" PRIu64", w %{public}d, h %{public}d, fps %{public}u",
121 display->GetId(), display->GetWidth(), display->GetHeight(), display->GetRefreshRate());
122 Rect displayRect = {0, 0,
123 static_cast<uint32_t>(display->GetWidth()), static_cast<uint32_t>(display->GetHeight())};
124 Utils::InitByDisplayRect(displayRect);
125 WindowManager::GetInstance().RegisterVisibilityChangedListener(visibilityChangedListener_);
126 auto displayId = DisplayManager::GetInstance().GetDefaultDisplayId();
127 WindowManager::GetInstance().MinimizeAllAppWindows(displayId);
128 }
129
TearDownTestCase()130 void WindowVisibilityInfoTest::TearDownTestCase()
131 {
132 WindowManager::GetInstance().UnregisterVisibilityChangedListener(visibilityChangedListener_);
133 }
134
SetUp()135 void WindowVisibilityInfoTest::SetUp()
136 {
137 fullScreenAppInfo_ = {
138 .name = "FullWindow",
139 .rect = Utils::customAppRect_,
140 .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW,
141 .mode = WindowMode::WINDOW_MODE_FULLSCREEN,
142 .needAvoid = false,
143 .parentLimit = false,
144 .showWhenLocked = true,
145 .parentId = INVALID_WINDOW_ID,
146 };
147 floatAppInfo_ = {
148 .name = "ParentWindow",
149 .rect = Utils::customAppRect_,
150 .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW,
151 .mode = WindowMode::WINDOW_MODE_FLOATING,
152 .needAvoid = false,
153 .parentLimit = false,
154 .showWhenLocked = true,
155 .parentId = INVALID_WINDOW_ID,
156 };
157 subAppInfo_ = {
158 .name = "SubWindow",
159 .rect = Utils::customAppRect_,
160 .type = WindowType::WINDOW_TYPE_APP_SUB_WINDOW,
161 .mode = WindowMode::WINDOW_MODE_FLOATING,
162 .needAvoid = false,
163 .parentLimit = false,
164 .showWhenLocked = true,
165 .parentId = INVALID_WINDOW_ID,
166 };
167 }
168
TearDown()169 void WindowVisibilityInfoTest::TearDown()
170 {
171 }
172
WaitForCallback()173 void WindowVisibilityInfoTest::WaitForCallback()
174 {
175 std::unique_lock<std::mutex> lock(mutex_);
176 visibilityChangedListener_->isCallbackCalled_ = false;
177 visibilityChangedListener_->windowVisibilityInfos_.clear();
178 auto now = std::chrono::system_clock::now();
179 if (!cv_.wait_until(lock, now + std::chrono::milliseconds(WAIT_ASYNC_MS_TIME_OUT),
180 []() { return visibilityChangedListener_->isCallbackCalled_; })) {
181 WLOGI("wait_until time out");
182 }
183 }
184
185 namespace {
186 /**
187 * @tc.name: WindowVisibilityInfoTest01
188 * @tc.desc: window show or hide
189 * @tc.type: FUNC
190 * @tc.require: issueI5FSQW
191 */
192 HWTEST_F(WindowVisibilityInfoTest, WindowVisibilityInfoTest01, Function | MediumTest | Level1)
193 {
194 floatAppInfo_.name = "window1";
195 floatAppInfo_.rect = {0, 0, 300, 100};
196 sptr<Window> window1 = Utils::CreateTestWindow(floatAppInfo_);
197 if (window1 == nullptr) {
198 return;
199 }
200
201 subAppInfo_.name = "subWindow1";
202 subAppInfo_.rect = {0, 600, 300, 100};
203 subAppInfo_.parentId = window1->GetWindowId();
204 sptr<Window> subWindow1 = Utils::CreateTestWindow(subAppInfo_);
205 ASSERT_NE(nullptr, subWindow1);
206 bool isWindowVisible = false;
207 bool isSubWindowVisible = false;
208
209 [[maybe_unused]] uint32_t visibilityInfoCount = 0;
210 ASSERT_EQ(WMError::WM_OK, window1->Show());
211 isWindowVisible = FillColor(window1);
212 WaitForCallback();
213 visibilityInfoCount = isWindowVisible ? 1 : 0;
214 ResetCallbackCalledFLag();
215
216 ASSERT_EQ(WMError::WM_OK, subWindow1->Show());
217 isSubWindowVisible = FillColor(subWindow1);
218 WaitForCallback();
219 visibilityInfoCount = isSubWindowVisible ? 1 : 0;
220 ResetCallbackCalledFLag();
221
222 ASSERT_EQ(WMError::WM_OK, subWindow1->Hide());
223 WaitForCallback();
224 visibilityInfoCount = isSubWindowVisible ? 1 : 0;
225 ResetCallbackCalledFLag();
226
227 ASSERT_EQ(WMError::WM_OK, window1->Hide());
228 WaitForCallback();
229 visibilityInfoCount = isWindowVisible ? 1 : 0;
230 ResetCallbackCalledFLag();
231
232 window1->Destroy();
233 subWindow1->Destroy();
234 sleep(2);
235 }
236 }
237 } // namespace Rosen
238 } // namespace OHOS
239
240