1 /*
2 * Copyright (c) 2024 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 #include <gtest/gtest.h>
17 #include <regex>
18 #include <pointer_event.h>
19 #include <ui/rs_surface_node.h>
20
21 #include "mock/mock_session_stage.h"
22 #include "mock/mock_window_event_channel.h"
23 #include "mock/mock_pattern_detach_callback.h"
24 #include "session/host/include/extension_session.h"
25 #include "session/host/include/move_drag_controller.h"
26 #include "session/host/include/scene_session.h"
27 #include "session_manager/include/scene_session_manager.h"
28 #include "session/host/include/session.h"
29 #include "session_info.h"
30 #include "key_event.h"
31 #include "wm_common.h"
32 #include "window_manager_hilog.h"
33
34 using namespace testing;
35 using namespace testing::ext;
36
37 namespace OHOS {
38 namespace Rosen {
39 namespace {
40 const std::string UNDEFINED = "undefined";
41 }
42
43 class SessionLayoutTest : public testing::Test {
44 public:
45 static void SetUpTestCase();
46 static void TearDownTestCase();
47 void SetUp() override;
48 void TearDown() override;
49 int32_t GetTaskCount();
50 sptr<SceneSessionManager> ssm_;
51
52 private:
53 RSSurfaceNode::SharedPtr CreateRSSurfaceNode();
54 sptr<Session> session_ = nullptr;
55 static constexpr uint32_t WAIT_SYNC_IN_NS = 500000;
56
57 class TLifecycleListener : public ILifecycleListener {
58 public:
~TLifecycleListener()59 virtual ~TLifecycleListener() {}
OnActivation()60 void OnActivation() override {}
OnConnect()61 void OnConnect() override {}
OnForeground()62 void OnForeground() override {}
OnBackground()63 void OnBackground() override {}
OnDisconnect()64 void OnDisconnect() override {}
OnExtensionDied()65 void OnExtensionDied() override {}
OnExtensionTimeout(int32_t errorCode)66 void OnExtensionTimeout(int32_t errorCode) override {}
OnAccessibilityEvent(const Accessibility::AccessibilityEventInfo & info,int64_t uiExtensionIdLevel)67 void OnAccessibilityEvent(const Accessibility::AccessibilityEventInfo& info,
68 int64_t uiExtensionIdLevel) override
69 {
70 }
OnDrawingCompleted()71 void OnDrawingCompleted() override {}
OnAppRemoveStartingWindow()72 void OnAppRemoveStartingWindow() override {}
73 };
74 std::shared_ptr<TLifecycleListener> lifecycleListener_ = std::make_shared<TLifecycleListener>();
75
76 sptr<SessionStageMocker> mockSessionStage_ = nullptr;
77 sptr<WindowEventChannelMocker> mockEventChannel_ = nullptr;
78 };
79
SetUpTestCase()80 void SessionLayoutTest::SetUpTestCase() {}
81
TearDownTestCase()82 void SessionLayoutTest::TearDownTestCase() {}
83
SetUp()84 void SessionLayoutTest::SetUp()
85 {
86 SessionInfo info;
87 info.abilityName_ = "testSession1";
88 info.moduleName_ = "testSession2";
89 info.bundleName_ = "testSession3";
90 session_ = sptr<Session>::MakeSptr(info);
91 session_->surfaceNode_ = CreateRSSurfaceNode();
92 ssm_ = sptr<SceneSessionManager>::MakeSptr();
93 session_->SetEventHandler(ssm_->taskScheduler_->GetEventHandler(), ssm_->eventHandler_);
94 auto isScreenLockedCallback = [this]() { return ssm_->IsScreenLocked(); };
95 session_->RegisterIsScreenLockedCallback(isScreenLockedCallback);
96 mockSessionStage_ = sptr<SessionStageMocker>::MakeSptr();
97 mockEventChannel_ = sptr<WindowEventChannelMocker>::MakeSptr(mockSessionStage_);
98 }
99
TearDown()100 void SessionLayoutTest::TearDown()
101 {
102 session_ = nullptr;
103 usleep(WAIT_SYNC_IN_NS);
104 }
105
CreateRSSurfaceNode()106 RSSurfaceNode::SharedPtr SessionLayoutTest::CreateRSSurfaceNode()
107 {
108 struct RSSurfaceNodeConfig rsSurfaceNodeConfig;
109 rsSurfaceNodeConfig.SurfaceNodeName = "WindowSessionTestSurfaceNode";
110 auto surfaceNode = RSSurfaceNode::Create(rsSurfaceNodeConfig);
111 if (surfaceNode == nullptr) {
112 GTEST_LOG_(INFO) << "SessionLayoutTest::CreateRSSurfaceNode surfaceNode is nullptr";
113 }
114 return surfaceNode;
115 }
116
GetTaskCount()117 int32_t SessionLayoutTest::GetTaskCount()
118 {
119 std::string dumpInfo = session_->handler_->GetEventRunner()->GetEventQueue()->DumpCurrentQueueSize();
120 std::regex pattern("\\d+");
121 std::smatch matches;
122 int32_t taskNum = 0;
123 while (std::regex_search(dumpInfo, matches, pattern)) {
124 taskNum += std::stoi(matches.str());
125 dumpInfo = matches.suffix();
126 }
127 return taskNum;
128 }
129
130 namespace {
131 /**
132 * @tc.name: UpdateRect01
133 * @tc.desc: update rect
134 * @tc.type: FUNC
135 * @tc.require: #I6JLSI
136 */
137 HWTEST_F(SessionLayoutTest, UpdateRect01, TestSize.Level1)
138 {
139 bool preBackgroundUpdateRectNotifyEnabled = Session::IsBackgroundUpdateRectNotifyEnabled();
140 Session::SetBackgroundUpdateRectNotifyEnabled(true);
141 sptr<SessionStageMocker> mockSessionStage = sptr<SessionStageMocker>::MakeSptr();
142 session_->sessionStage_ = mockSessionStage;
143 EXPECT_CALL(*(mockSessionStage), UpdateRect(_, _, _, _)).Times(AtLeast(1)).WillOnce(Return(WSError::WS_OK));
144
145 WSRect rect = { 0, 0, 0, 0 };
146 ASSERT_EQ(WSError::WS_ERROR_INVALID_SESSION,
147 session_->UpdateRect(rect, SizeChangeReason::UNDEFINED, "SessionLayoutTest"));
148 sptr<WindowEventChannelMocker> mockEventChannel = sptr<WindowEventChannelMocker>::MakeSptr(mockSessionStage);
149 SystemSessionConfig sessionConfig;
150 sptr<WindowSessionProperty> property = sptr<WindowSessionProperty>::MakeSptr();
151 ASSERT_EQ(WSError::WS_OK, session_->Connect(mockSessionStage, mockEventChannel, nullptr, sessionConfig, property));
152
153 rect = { 0, 0, 100, 100 };
154 ASSERT_EQ(WSError::WS_ERROR_INVALID_SESSION,
155 session_->UpdateRect(rect, SizeChangeReason::UNDEFINED, "SessionLayoutTest"));
156 ASSERT_EQ(rect, session_->GetSessionRect());
157
158 rect = { 0, 0, 200, 200 };
159 session_->UpdateSessionState(SessionState::STATE_ACTIVE);
160 ASSERT_EQ(WSError::WS_OK, session_->UpdateRect(rect, SizeChangeReason::UNDEFINED, "SessionLayoutTest"));
161 ASSERT_EQ(rect, session_->GetSessionRect());
162
163 rect = { 0, 0, 300, 300 };
164 session_->sessionStage_ = nullptr;
165 ASSERT_EQ(WSError::WS_OK, session_->UpdateRect(rect, SizeChangeReason::UNDEFINED, "SessionLayoutTest"));
166 ASSERT_EQ(rect, session_->GetSessionRect());
167 Session::SetBackgroundUpdateRectNotifyEnabled(preBackgroundUpdateRectNotifyEnabled);
168 }
169
170 /**
171 * @tc.name: UpdateRect_TestForeground
172 * @tc.desc: update rect
173 * @tc.type: FUNC
174 * @tc.require: #I6JLSI
175 */
176 HWTEST_F(SessionLayoutTest, UpdateRect_TestForeground, TestSize.Level1)
177 {
178 bool preBackgroundUpdateRectNotifyEnabled = Session::IsBackgroundUpdateRectNotifyEnabled();
179 Session::SetBackgroundUpdateRectNotifyEnabled(false);
180 sptr<SessionStageMocker> mockSessionStage = sptr<SessionStageMocker>::MakeSptr();
181 session_->sessionStage_ = mockSessionStage;
182
183 WSRect rect = { 0, 0, 100, 100 };
184 session_->UpdateSessionState(SessionState::STATE_ACTIVE);
185 ASSERT_EQ(WSError::WS_OK, session_->UpdateRect(rect, SizeChangeReason::UNDEFINED, "SessionLayoutTest"));
186 session_->UpdateSessionState(SessionState::STATE_BACKGROUND);
187 ASSERT_EQ(WSError::WS_DO_NOTHING, session_->UpdateRect(rect, SizeChangeReason::UNDEFINED, "SessionLayoutTest"));
188 Session::SetBackgroundUpdateRectNotifyEnabled(preBackgroundUpdateRectNotifyEnabled);
189 }
190
191 /**
192 * @tc.name: UpdateSessionRect01
193 * @tc.desc: UpdateSessionRect
194 * @tc.type: FUNC
195 */
196 HWTEST_F(SessionLayoutTest, UpdateSessionRect01, TestSize.Level1)
197 {
198 SessionInfo info;
199 info.abilityName_ = "testSession1";
200 info.bundleName_ = "testSession3";
201 sptr<SceneSession> sceneSession = sptr<SceneSession>::MakeSptr(info, nullptr);
202 WSRect rect = { 0, 0, 320, 240 }; // width: 320, height: 240
203 auto result = sceneSession->UpdateSessionRect(rect, SizeChangeReason::RESIZE);
204 ASSERT_EQ(result, WSError::WS_OK);
205
206 result = sceneSession->UpdateSessionRect(rect, SizeChangeReason::RESIZE);
207 ASSERT_EQ(result, WSError::WS_OK);
208 }
209
210 /**
211 * @tc.name: SetSingleHandTransform
212 * @tc.desc: SetSingleHandTransform
213 * @tc.type: FUNC
214 */
215 HWTEST_F(SessionLayoutTest, SetSingleHandTransform, TestSize.Level1)
216 {
217 SessionInfo info;
218 info.abilityName_ = "SetSingleHandTransform";
219 info.bundleName_ = "SetSingleHandTransform";
220 sptr<Session> session = sptr<Session>::MakeSptr(info);
221 SingleHandTransform transform;
222 session->SetSingleHandTransform(transform);
223 ASSERT_EQ(transform, session->GetSingleHandTransform());
224 }
225
226 /**
227 * @tc.name: IsDraggingReason
228 * @tc.desc: IsDraggingReason
229 * @tc.type: FUNC
230 */
231 HWTEST_F(SessionLayoutTest, IsDraggingReason, TestSize.Level1)
232 {
233 SessionInfo info;
234 info.abilityName_ = "IsDraggingReason";
235 info.bundleName_ = "IsDraggingReason";
236 sptr<Session> session = sptr<Session>::MakeSptr(info);
237 ASSERT_EQ(false, session->IsDraggingReason(SizeChangeReason::UNDEFINED));
238 ASSERT_EQ(true, session->IsDraggingReason(SizeChangeReason::DRAG));
239 ASSERT_EQ(true, session->IsDraggingReason(SizeChangeReason::DRAG_START));
240 ASSERT_EQ(true, session->IsDraggingReason(SizeChangeReason::DRAG_MOVE));
241 }
242
243 /**
244 * @tc.name: SetDragStart
245 * @tc.desc: SetDragStart
246 * @tc.type: FUNC
247 */
248 HWTEST_F(SessionLayoutTest, SetDragStart, TestSize.Level1)
249 {
250 SessionInfo info;
251 info.abilityName_ = "SetDragStart";
252 info.bundleName_ = "SetDragStart";
253 sptr<Session> session = sptr<Session>::MakeSptr(info);
254 session->SetDragStart(true);
255 ASSERT_EQ(true, session->IsDragStart());
256 session->SetDragStart(false);
257 ASSERT_EQ(false, session->IsDragStart());
258 }
259
260 /**
261 * @tc.name: UpdateWindowModeSupportType01
262 * @tc.desc: UpdateWindowModeSupportType
263 * @tc.type: FUNC
264 */
265 HWTEST_F(SessionLayoutTest, UpdateWindowModeSupportType01, TestSize.Level1)
266 {
267 SessionInfo info;
268 info.abilityName_ = "UpdateWindowModeSupportType01";
269 info.bundleName_ = "UpdateWindowModeSupportType01";
270 sptr<Session> session = sptr<Session>::MakeSptr(info);
271
272 EXPECT_EQ(session->UpdateWindowModeSupportType(nullptr), false);
273
274 std::shared_ptr<AppExecFwk::AbilityInfo> abilityInfo = std::make_shared<AppExecFwk::AbilityInfo>();
275 EXPECT_EQ(session->UpdateWindowModeSupportType(abilityInfo), false);
276 }
277
278 /**
279 * @tc.name: SetHasRequestedVsyncFunc
280 * @tc.desc: SetHasRequestedVsyncFunc
281 * @tc.type: FUNC
282 */
283 HWTEST_F(SessionLayoutTest, SetHasRequestedVsyncFunc, TestSize.Level1)
284 {
285 SessionInfo info;
286 info.abilityName_ = "SetHasRequestedVsyncFunc";
287 info.bundleName_ = "SetHasRequestedVsyncFunc";
288 sptr<Session> session = sptr<Session>::MakeSptr(info);
289 session->SetHasRequestedVsyncFunc(nullptr);
290 ASSERT_EQ(nullptr, session->hasRequestedVsyncFunc_);
__anon1b52b2e90402(bool& hasRequestedVsync) 291 session->SetHasRequestedVsyncFunc([](bool& hasRequestedVsync) {
292 hasRequestedVsync = true;
293 return WSError::WS_OK;
294 });
295 ASSERT_NE(nullptr, session->hasRequestedVsyncFunc_);
296 }
297
298 /**
299 * @tc.name: SetRequestNextVsyncWhenModeChangeFunc
300 * @tc.desc: SetRequestNextVsyncWhenModeChangeFunc
301 * @tc.type: FUNC
302 */
303 HWTEST_F(SessionLayoutTest, SetRequestNextVsyncWhenModeChangeFunc, TestSize.Level1)
304 {
305 SessionInfo info;
306 info.abilityName_ = "SetRequestNextVsyncWhenModeChangeFunc";
307 info.bundleName_ = "SetRequestNextVsyncWhenModeChangeFunc";
308 sptr<Session> session = sptr<Session>::MakeSptr(info);
309 session->SetRequestNextVsyncWhenModeChangeFunc(nullptr);
310 ASSERT_EQ(nullptr, session->requestNextVsyncWhenModeChangeFunc_);
__anon1b52b2e90502(const std::shared_ptr<VsyncCallback>& vsyncCallback) 311 session->SetRequestNextVsyncWhenModeChangeFunc([](const std::shared_ptr<VsyncCallback>& vsyncCallback) {
312 return WSError::WS_OK;
313 });
314 ASSERT_NE(nullptr, session->requestNextVsyncWhenModeChangeFunc_);
315 }
316
317 /**
318 * @tc.name: RequestNextVsyncWhenModeChange
319 * @tc.desc: RequestNextVsyncWhenModeChange
320 * @tc.type: FUNC
321 */
322 HWTEST_F(SessionLayoutTest, RequestNextVsyncWhenModeChange, TestSize.Level1)
323 {
324 SessionInfo info;
325 info.abilityName_ = "RequestNextVsyncWhenModeChange";
326 info.bundleName_ = "RequestNextVsyncWhenModeChange";
327 sptr<Session> session = sptr<Session>::MakeSptr(info);
328 auto ret = session->RequestNextVsyncWhenModeChange();
329 EXPECT_EQ(WSError::WS_ERROR_NULLPTR, ret);
__anon1b52b2e90602(bool& hasRequestedVsync) 330 session->SetHasRequestedVsyncFunc([](bool& hasRequestedVsync) {
331 hasRequestedVsync = true;
332 return WSError::WS_OK;
333 });
334 ret = session->RequestNextVsyncWhenModeChange();
335 EXPECT_EQ(WSError::WS_OK, ret);
336 }
337
338 /**
339 * @tc.name: InitVsyncCallbackForModeChangeAndRequestNextVsync
340 * @tc.desc: InitVsyncCallbackForModeChangeAndRequestNextVsync
341 * @tc.type: FUNC
342 */
343 HWTEST_F(SessionLayoutTest, InitVsyncCallbackForModeChangeAndRequestNextVsync, TestSize.Level1)
344 {
345 SessionInfo info;
346 info.abilityName_ = "InitVsyncCallbackForModeChangeAndRequestNextVsync";
347 info.bundleName_ = "InitVsyncCallbackForModeChangeAndRequestNextVsync";
348 sptr<Session> session = sptr<Session>::MakeSptr(info);
349 session->isWindowModeDirty_.store(true);
350 session->timesToWaitForVsync_.store(2);
351 session->requestNextVsyncWhenModeChangeFunc_ = nullptr;
352 session->InitVsyncCallbackForModeChangeAndRequestNextVsync();
353 usleep(WAIT_SYNC_IN_NS);
354 EXPECT_EQ(session->timesToWaitForVsync_.load(), 2);
355
__anon1b52b2e90702(const std::shared_ptr<VsyncCallback>& vsyncCallback) 356 session->SetRequestNextVsyncWhenModeChangeFunc([](const std::shared_ptr<VsyncCallback>& vsyncCallback) {
357 vsyncCallback->onCallback(1, 1);
358 return WSError::WS_OK;
359 });
360 session->InitVsyncCallbackForModeChangeAndRequestNextVsync();
361 usleep(WAIT_SYNC_IN_NS);
362 EXPECT_NE(session->timesToWaitForVsync_.load(), 2);
363 }
364
365 /**
366 * @tc.name: OnVsyncReceivedAfterModeChanged
367 * @tc.desc: OnVsyncReceivedAfterModeChanged
368 * @tc.type: FUNC
369 */
370 HWTEST_F(SessionLayoutTest, OnVsyncReceivedAfterModeChanged, TestSize.Level1)
371 {
372 SessionInfo info;
373 info.abilityName_ = "OnVsyncReceivedAfterModeChanged";
374 info.bundleName_ = "OnVsyncReceivedAfterModeChanged";
375 sptr<Session> session = sptr<Session>::MakeSptr(info);
376 session->isWindowModeDirty_.store(false);
377 session->timesToWaitForVsync_.store(2);
378 session->OnVsyncReceivedAfterModeChanged();
379 usleep(WAIT_SYNC_IN_NS);
380 EXPECT_EQ(session->timesToWaitForVsync_.load(), 2);
381
__anon1b52b2e90802(const std::shared_ptr<VsyncCallback>& vsyncCallback) 382 session->SetRequestNextVsyncWhenModeChangeFunc([](const std::shared_ptr<VsyncCallback>& vsyncCallback) {
383 vsyncCallback->onCallback(1, 1);
384 return WSError::WS_OK;
385 });
386 session->isWindowModeDirty_.store(true);
387 session->OnVsyncReceivedAfterModeChanged();
388 usleep(WAIT_SYNC_IN_NS);
389 EXPECT_NE(session->timesToWaitForVsync_.load(), 2);
390
391 session->isWindowModeDirty_.store(true);
392 session->timesToWaitForVsync_.store(-1);
393 session->OnVsyncReceivedAfterModeChanged();
394 usleep(WAIT_SYNC_IN_NS);
395 EXPECT_EQ(session->timesToWaitForVsync_.load(), 0);
396
397 session->isWindowModeDirty_.store(true);
398 session->timesToWaitForVsync_.store(1);
399 session->sessionStage_ = nullptr;
400 session->OnVsyncReceivedAfterModeChanged();
401 usleep(WAIT_SYNC_IN_NS);
402 EXPECT_EQ(session->isWindowModeDirty_.load(), false);
403
404 session->isWindowModeDirty_.store(true);
405 session->timesToWaitForVsync_.store(1);
406 session->sessionStage_ = sptr<SessionStageMocker>::MakeSptr();
407 session->OnVsyncReceivedAfterModeChanged();
408 usleep(WAIT_SYNC_IN_NS);
409 EXPECT_EQ(session->isWindowModeDirty_.load(), false);
410 }
411
412 /**
413 * @tc.name: NotifyAppHookWindowInfoUpdated
414 * @tc.desc: NotifyAppHookWindowInfoUpdated
415 * @tc.type: FUNC
416 */
417 HWTEST_F(SessionLayoutTest, NotifyAppHookWindowInfoUpdated, TestSize.Level1)
418 {
419 SessionInfo info;
420 info.abilityName_ = "NotifyAppHookWindowInfoUpdated";
421 info.bundleName_ = "NotifyAppHookWindowInfoUpdated";
422 sptr<Session> session = sptr<Session>::MakeSptr(info);
423
424 session->sessionStage_ = nullptr;
425 WSError errCode = session->NotifyAppHookWindowInfoUpdated();
426 EXPECT_EQ(errCode, WSError::WS_ERROR_NULLPTR);
427
428 session->sessionStage_ = sptr<SessionStageMocker>::MakeSptr();
429 errCode = session->NotifyAppHookWindowInfoUpdated();
430 EXPECT_EQ(errCode, WSError::WS_OK);
431 }
432 } // namespace
433 } // namespace Rosen
434 } // namespace OHOS
435