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