blob: cbef68e2eb8f4f0eae7558a91c119f442b7077ba [file] [log] [blame]
Garfield Tanc15eb912019-08-05 16:47:40 -07001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Prabir Pradhan6c7aa6f2023-12-12 16:54:59 +000017#include <flag_macros.h>
Brandon Pollack015f5d92022-06-02 06:59:33 +000018#include <gmock/gmock.h>
19#include <gtest/gtest.h>
Garfield Tanc15eb912019-08-05 16:47:40 -070020#include <input/PointerController.h>
21#include <input/SpriteController.h>
22
23#include <atomic>
Garfield Tanc15eb912019-08-05 16:47:40 -070024#include <thread>
25
Brandon Pollack015f5d92022-06-02 06:59:33 +000026#include "input/Input.h"
27#include "mocks/MockSprite.h"
28#include "mocks/MockSpriteController.h"
29
Garfield Tanc15eb912019-08-05 16:47:40 -070030namespace android {
31
32enum TestCursorType {
33 CURSOR_TYPE_DEFAULT = 0,
34 CURSOR_TYPE_HOVER,
35 CURSOR_TYPE_TOUCH,
36 CURSOR_TYPE_ANCHOR,
Garfield Tane9c61512019-11-21 16:42:13 -080037 CURSOR_TYPE_ADDITIONAL,
38 CURSOR_TYPE_ADDITIONAL_ANIM,
Seunghwan Choi670b33d2023-01-13 21:12:59 +090039 CURSOR_TYPE_STYLUS,
Garfield Tanc15eb912019-08-05 16:47:40 -070040 CURSOR_TYPE_CUSTOM = -1,
41};
42
43using ::testing::AllOf;
44using ::testing::Field;
Prabir Pradhanca7d7232020-01-31 17:42:34 -080045using ::testing::NiceMock;
Garfield Tanc15eb912019-08-05 16:47:40 -070046using ::testing::Return;
47using ::testing::Test;
48
49std::pair<float, float> getHotSpotCoordinatesForType(int32_t type) {
50 return std::make_pair(type * 10, type * 10 + 5);
51}
52
53class MockPointerControllerPolicyInterface : public PointerControllerPolicyInterface {
54public:
Linnan Li0defadf2024-05-05 19:17:05 +080055 virtual void loadPointerIcon(SpriteIcon* icon, ui::LogicalDisplayId displayId) override;
56 virtual void loadPointerResources(PointerResources* outResources,
57 ui::LogicalDisplayId displayId) override;
Brandon Pollack015f5d92022-06-02 06:59:33 +000058 virtual void loadAdditionalMouseResources(
59 std::map<PointerIconStyle, SpriteIcon>* outResources,
60 std::map<PointerIconStyle, PointerAnimation>* outAnimationResources,
Linnan Li0defadf2024-05-05 19:17:05 +080061 ui::LogicalDisplayId displayId) override;
Brandon Pollack015f5d92022-06-02 06:59:33 +000062 virtual PointerIconStyle getDefaultPointerIconId() override;
Seunghwan Choi670b33d2023-01-13 21:12:59 +090063 virtual PointerIconStyle getDefaultStylusIconId() override;
Brandon Pollack015f5d92022-06-02 06:59:33 +000064 virtual PointerIconStyle getCustomPointerIconId() override;
Garfield Tanc15eb912019-08-05 16:47:40 -070065
Prabir Pradhanca7d7232020-01-31 17:42:34 -080066 bool allResourcesAreLoaded();
67 bool noResourcesAreLoaded();
68
Garfield Tanc15eb912019-08-05 16:47:40 -070069private:
70 void loadPointerIconForType(SpriteIcon* icon, int32_t cursorType);
Prabir Pradhanca7d7232020-01-31 17:42:34 -080071
72 bool pointerIconLoaded{false};
73 bool pointerResourcesLoaded{false};
74 bool additionalMouseResourcesLoaded{false};
Garfield Tanc15eb912019-08-05 16:47:40 -070075};
76
Linnan Li0defadf2024-05-05 19:17:05 +080077void MockPointerControllerPolicyInterface::loadPointerIcon(SpriteIcon* icon, ui::LogicalDisplayId) {
Garfield Tanc15eb912019-08-05 16:47:40 -070078 loadPointerIconForType(icon, CURSOR_TYPE_DEFAULT);
Prabir Pradhanca7d7232020-01-31 17:42:34 -080079 pointerIconLoaded = true;
Garfield Tanc15eb912019-08-05 16:47:40 -070080}
81
82void MockPointerControllerPolicyInterface::loadPointerResources(PointerResources* outResources,
Linnan Li0defadf2024-05-05 19:17:05 +080083 ui::LogicalDisplayId) {
Garfield Tanc15eb912019-08-05 16:47:40 -070084 loadPointerIconForType(&outResources->spotHover, CURSOR_TYPE_HOVER);
85 loadPointerIconForType(&outResources->spotTouch, CURSOR_TYPE_TOUCH);
86 loadPointerIconForType(&outResources->spotAnchor, CURSOR_TYPE_ANCHOR);
Prabir Pradhanca7d7232020-01-31 17:42:34 -080087 pointerResourcesLoaded = true;
Garfield Tanc15eb912019-08-05 16:47:40 -070088}
89
90void MockPointerControllerPolicyInterface::loadAdditionalMouseResources(
Brandon Pollack015f5d92022-06-02 06:59:33 +000091 std::map<PointerIconStyle, SpriteIcon>* outResources,
Linnan Li0defadf2024-05-05 19:17:05 +080092 std::map<PointerIconStyle, PointerAnimation>* outAnimationResources, ui::LogicalDisplayId) {
Garfield Tanc15eb912019-08-05 16:47:40 -070093 SpriteIcon icon;
94 PointerAnimation anim;
95
Garfield Tane9c61512019-11-21 16:42:13 -080096 // CURSOR_TYPE_ADDITIONAL doesn't have animation resource.
97 int32_t cursorType = CURSOR_TYPE_ADDITIONAL;
98 loadPointerIconForType(&icon, cursorType);
Brandon Pollack015f5d92022-06-02 06:59:33 +000099 (*outResources)[static_cast<PointerIconStyle>(cursorType)] = icon;
Garfield Tane9c61512019-11-21 16:42:13 -0800100
101 // CURSOR_TYPE_ADDITIONAL_ANIM has animation resource.
102 cursorType = CURSOR_TYPE_ADDITIONAL_ANIM;
103 loadPointerIconForType(&icon, cursorType);
104 anim.animationFrames.push_back(icon);
105 anim.durationPerFrame = 10;
Brandon Pollack015f5d92022-06-02 06:59:33 +0000106 (*outResources)[static_cast<PointerIconStyle>(cursorType)] = icon;
107 (*outAnimationResources)[static_cast<PointerIconStyle>(cursorType)] = anim;
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800108
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900109 // CURSOR_TYPE_STYLUS doesn't have animation resource.
110 cursorType = CURSOR_TYPE_STYLUS;
111 loadPointerIconForType(&icon, cursorType);
112 (*outResources)[static_cast<PointerIconStyle>(cursorType)] = icon;
113
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800114 additionalMouseResourcesLoaded = true;
Garfield Tanc15eb912019-08-05 16:47:40 -0700115}
116
Brandon Pollack015f5d92022-06-02 06:59:33 +0000117PointerIconStyle MockPointerControllerPolicyInterface::getDefaultPointerIconId() {
118 return static_cast<PointerIconStyle>(CURSOR_TYPE_DEFAULT);
Garfield Tanc15eb912019-08-05 16:47:40 -0700119}
120
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900121PointerIconStyle MockPointerControllerPolicyInterface::getDefaultStylusIconId() {
122 return static_cast<PointerIconStyle>(CURSOR_TYPE_STYLUS);
123}
124
Brandon Pollack015f5d92022-06-02 06:59:33 +0000125PointerIconStyle MockPointerControllerPolicyInterface::getCustomPointerIconId() {
126 return static_cast<PointerIconStyle>(CURSOR_TYPE_CUSTOM);
Garfield Tanc15eb912019-08-05 16:47:40 -0700127}
128
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800129bool MockPointerControllerPolicyInterface::allResourcesAreLoaded() {
130 return pointerIconLoaded && pointerResourcesLoaded && additionalMouseResourcesLoaded;
131}
132
133bool MockPointerControllerPolicyInterface::noResourcesAreLoaded() {
134 return !(pointerIconLoaded || pointerResourcesLoaded || additionalMouseResourcesLoaded);
135}
136
Garfield Tanc15eb912019-08-05 16:47:40 -0700137void MockPointerControllerPolicyInterface::loadPointerIconForType(SpriteIcon* icon, int32_t type) {
Brandon Pollack015f5d92022-06-02 06:59:33 +0000138 icon->style = static_cast<PointerIconStyle>(type);
Garfield Tanc15eb912019-08-05 16:47:40 -0700139 std::pair<float, float> hotSpot = getHotSpotCoordinatesForType(type);
140 icon->hotSpotX = hotSpot.first;
141 icon->hotSpotY = hotSpot.second;
142}
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000143
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700144class TestPointerController : public PointerController {
145public:
146 TestPointerController(sp<android::gui::WindowInfosListener>& registeredListener,
147 sp<PointerControllerPolicyInterface> policy, const sp<Looper>& looper,
148 SpriteController& spriteController)
149 : PointerController(
150 policy, looper, spriteController,
Linnan Li37c1b992023-11-24 13:05:13 +0800151 [&registeredListener](const sp<android::gui::WindowInfosListener>& listener)
Prabir Pradhanbdf93692024-01-23 18:08:28 +0000152 -> std::vector<gui::DisplayInfo> {
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700153 // Register listener
154 registeredListener = listener;
Linnan Li37c1b992023-11-24 13:05:13 +0800155 return {};
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700156 },
157 [&registeredListener](const sp<android::gui::WindowInfosListener>& listener) {
158 // Unregister listener
159 if (registeredListener == listener) registeredListener = nullptr;
160 }) {}
161 ~TestPointerController() override {}
162};
163
Garfield Tanc15eb912019-08-05 16:47:40 -0700164class PointerControllerTest : public Test {
165protected:
166 PointerControllerTest();
167 ~PointerControllerTest();
168
Siarhei Vishniakou445af182024-05-13 13:17:05 -0700169 void ensureDisplayViewportIsSet(ui::LogicalDisplayId displayId = ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800170
Garfield Tanc15eb912019-08-05 16:47:40 -0700171 sp<MockSprite> mPointerSprite;
172 sp<MockPointerControllerPolicyInterface> mPolicy;
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000173 std::unique_ptr<MockSpriteController> mSpriteController;
Michael Wrighta0bc6b12020-06-26 20:25:34 +0100174 std::shared_ptr<PointerController> mPointerController;
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700175 sp<android::gui::WindowInfosListener> mRegisteredListener;
Garfield Tanc15eb912019-08-05 16:47:40 -0700176
177private:
178 void loopThread();
179
180 std::atomic<bool> mRunning = true;
181 class MyLooper : public Looper {
182 public:
183 MyLooper() : Looper(false) {}
184 ~MyLooper() = default;
185 };
Garfield Tanc15eb912019-08-05 16:47:40 -0700186 std::thread mThread;
Arpit Singhf4ae0ac2024-03-26 18:41:06 +0000187
188protected:
189 sp<MyLooper> mLooper;
Garfield Tanc15eb912019-08-05 16:47:40 -0700190};
191
Arpit Singhf4ae0ac2024-03-26 18:41:06 +0000192PointerControllerTest::PointerControllerTest()
193 : mPointerSprite(new NiceMock<MockSprite>),
194 mThread(&PointerControllerTest::loopThread, this),
195 mLooper(new MyLooper) {
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000196 mSpriteController.reset(new NiceMock<MockSpriteController>(mLooper));
Garfield Tanc15eb912019-08-05 16:47:40 -0700197 mPolicy = new MockPointerControllerPolicyInterface();
198
199 EXPECT_CALL(*mSpriteController, createSprite())
200 .WillOnce(Return(mPointerSprite));
201
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700202 mPointerController = std::make_unique<TestPointerController>(mRegisteredListener, mPolicy,
203 mLooper, *mSpriteController);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800204}
Garfield Tanc15eb912019-08-05 16:47:40 -0700205
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800206PointerControllerTest::~PointerControllerTest() {
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700207 mPointerController.reset();
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800208 mRunning.store(false, std::memory_order_relaxed);
209 mThread.join();
210}
211
Linnan Li0defadf2024-05-05 19:17:05 +0800212void PointerControllerTest::ensureDisplayViewportIsSet(ui::LogicalDisplayId displayId) {
Garfield Tanc15eb912019-08-05 16:47:40 -0700213 DisplayViewport viewport;
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000214 viewport.displayId = displayId;
Garfield Tanc15eb912019-08-05 16:47:40 -0700215 viewport.logicalRight = 1600;
216 viewport.logicalBottom = 1200;
217 viewport.physicalRight = 800;
218 viewport.physicalBottom = 600;
219 viewport.deviceWidth = 400;
220 viewport.deviceHeight = 300;
221 mPointerController->setDisplayViewport(viewport);
Garfield Tanc15eb912019-08-05 16:47:40 -0700222}
223
224void PointerControllerTest::loopThread() {
225 Looper::setForThread(mLooper);
226
227 while (mRunning.load(std::memory_order_relaxed)) {
228 mLooper->pollOnce(100);
229 }
230}
231
232TEST_F(PointerControllerTest, useDefaultCursorTypeByDefault) {
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800233 ensureDisplayViewportIsSet();
Michael Wright6853fe62020-07-02 00:01:38 +0100234 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
Garfield Tanc15eb912019-08-05 16:47:40 -0700235
236 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(CURSOR_TYPE_DEFAULT);
237 EXPECT_CALL(*mPointerSprite, setVisible(true));
238 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
Brandon Pollack015f5d92022-06-02 06:59:33 +0000239 EXPECT_CALL(*mPointerSprite,
240 setIcon(AllOf(Field(&SpriteIcon::style,
241 static_cast<PointerIconStyle>(CURSOR_TYPE_DEFAULT)),
242 Field(&SpriteIcon::hotSpotX, hotspot.first),
243 Field(&SpriteIcon::hotSpotY, hotspot.second))));
Garfield Tanc15eb912019-08-05 16:47:40 -0700244 mPointerController->reloadPointerResources();
245}
246
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900247TEST_F(PointerControllerTest, useStylusTypeForStylusHover) {
248 ensureDisplayViewportIsSet();
249 mPointerController->setPresentation(PointerController::Presentation::STYLUS_HOVER);
250 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
251 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(CURSOR_TYPE_STYLUS);
252 EXPECT_CALL(*mPointerSprite, setVisible(true));
253 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
254 EXPECT_CALL(*mPointerSprite,
255 setIcon(AllOf(Field(&SpriteIcon::style,
256 static_cast<PointerIconStyle>(CURSOR_TYPE_STYLUS)),
257 Field(&SpriteIcon::hotSpotX, hotspot.first),
258 Field(&SpriteIcon::hotSpotY, hotspot.second))));
259 mPointerController->reloadPointerResources();
260}
261
Prabir Pradhan7dff1422024-05-03 23:33:28 +0000262TEST_F(PointerControllerTest, setPresentationBeforeDisplayViewportDoesNotLoadResources) {
Prabir Pradhan6c7aa6f2023-12-12 16:54:59 +0000263 // Setting the presentation mode before a display viewport is set will not load any resources.
264 mPointerController->setPresentation(PointerController::Presentation::POINTER);
265 ASSERT_TRUE(mPolicy->noResourcesAreLoaded());
266
267 // When the display is set, then the resources are loaded.
268 ensureDisplayViewportIsSet();
269 ASSERT_TRUE(mPolicy->allResourcesAreLoaded());
270}
271
Prabir Pradhan7dff1422024-05-03 23:33:28 +0000272TEST_F(PointerControllerTest, updatePointerIconWithChoreographer) {
Prabir Pradhan6c7aa6f2023-12-12 16:54:59 +0000273 // When PointerChoreographer is enabled, the presentation mode is set before the viewport.
274 mPointerController->setPresentation(PointerController::Presentation::POINTER);
275 ensureDisplayViewportIsSet();
276 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
277
278 int32_t type = CURSOR_TYPE_ADDITIONAL;
279 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(type);
280 EXPECT_CALL(*mPointerSprite, setVisible(true));
281 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
282 EXPECT_CALL(*mPointerSprite,
283 setIcon(AllOf(Field(&SpriteIcon::style, static_cast<PointerIconStyle>(type)),
284 Field(&SpriteIcon::hotSpotX, hotspot.first),
285 Field(&SpriteIcon::hotSpotY, hotspot.second))));
286 mPointerController->updatePointerIcon(static_cast<PointerIconStyle>(type));
287}
288
Garfield Tanc15eb912019-08-05 16:47:40 -0700289TEST_F(PointerControllerTest, setCustomPointerIcon) {
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800290 ensureDisplayViewportIsSet();
Michael Wright6853fe62020-07-02 00:01:38 +0100291 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
Garfield Tanc15eb912019-08-05 16:47:40 -0700292
293 int32_t style = CURSOR_TYPE_CUSTOM;
294 float hotSpotX = 15;
295 float hotSpotY = 20;
296
297 SpriteIcon icon;
Brandon Pollack015f5d92022-06-02 06:59:33 +0000298 icon.style = static_cast<PointerIconStyle>(style);
Garfield Tanc15eb912019-08-05 16:47:40 -0700299 icon.hotSpotX = hotSpotX;
300 icon.hotSpotY = hotSpotY;
301
302 EXPECT_CALL(*mPointerSprite, setVisible(true));
303 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
Brandon Pollack015f5d92022-06-02 06:59:33 +0000304 EXPECT_CALL(*mPointerSprite,
305 setIcon(AllOf(Field(&SpriteIcon::style, static_cast<PointerIconStyle>(style)),
306 Field(&SpriteIcon::hotSpotX, hotSpotX),
307 Field(&SpriteIcon::hotSpotY, hotSpotY))));
Garfield Tanc15eb912019-08-05 16:47:40 -0700308 mPointerController->setCustomPointerIcon(icon);
309}
310
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800311TEST_F(PointerControllerTest, doesNotGetResourcesBeforeSettingViewport) {
Michael Wright6853fe62020-07-02 00:01:38 +0100312 mPointerController->setPresentation(PointerController::Presentation::POINTER);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800313 mPointerController->setPosition(1.0f, 1.0f);
314 mPointerController->move(1.0f, 1.0f);
Michael Wright6853fe62020-07-02 00:01:38 +0100315 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
316 mPointerController->fade(PointerController::Transition::IMMEDIATE);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800317
318 EXPECT_TRUE(mPolicy->noResourcesAreLoaded());
319
320 ensureDisplayViewportIsSet();
321}
322
Arpit Singh80fd68a2024-03-26 18:41:06 +0000323TEST_F(PointerControllerTest, updatesSkipScreenshotFlagForTouchSpots) {
324 ensureDisplayViewportIsSet();
325
326 PointerCoords testSpotCoords;
327 testSpotCoords.clear();
328 testSpotCoords.setAxisValue(AMOTION_EVENT_AXIS_X, 1);
329 testSpotCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, 1);
330 BitSet32 testIdBits;
331 testIdBits.markBit(0);
332 std::array<uint32_t, MAX_POINTER_ID + 1> testIdToIndex;
333
334 sp<MockSprite> testSpotSprite(new NiceMock<MockSprite>);
335
336 // By default sprite is not marked secure
337 EXPECT_CALL(*mSpriteController, createSprite).WillOnce(Return(testSpotSprite));
338 EXPECT_CALL(*testSpotSprite, setSkipScreenshot).With(testing::Args<0>(false));
339
340 // Update spots to sync state with sprite
341 mPointerController->setSpots(&testSpotCoords, testIdToIndex.cbegin(), testIdBits,
Siarhei Vishniakou445af182024-05-13 13:17:05 -0700342 ui::LogicalDisplayId::DEFAULT);
Arpit Singh80fd68a2024-03-26 18:41:06 +0000343 testing::Mock::VerifyAndClearExpectations(testSpotSprite.get());
344
345 // Marking the display to skip screenshot should update sprite as well
Arpit Singhf4ae0ac2024-03-26 18:41:06 +0000346 mPointerController->setSkipScreenshotFlagForDisplay(ui::LogicalDisplayId::DEFAULT);
Arpit Singh80fd68a2024-03-26 18:41:06 +0000347 EXPECT_CALL(*testSpotSprite, setSkipScreenshot).With(testing::Args<0>(true));
348
349 // Update spots to sync state with sprite
350 mPointerController->setSpots(&testSpotCoords, testIdToIndex.cbegin(), testIdBits,
Siarhei Vishniakou445af182024-05-13 13:17:05 -0700351 ui::LogicalDisplayId::DEFAULT);
Arpit Singh80fd68a2024-03-26 18:41:06 +0000352 testing::Mock::VerifyAndClearExpectations(testSpotSprite.get());
353
354 // Reset flag and verify again
Arpit Singhf4ae0ac2024-03-26 18:41:06 +0000355 mPointerController->clearSkipScreenshotFlags();
Arpit Singh80fd68a2024-03-26 18:41:06 +0000356 EXPECT_CALL(*testSpotSprite, setSkipScreenshot).With(testing::Args<0>(false));
357 mPointerController->setSpots(&testSpotCoords, testIdToIndex.cbegin(), testIdBits,
Siarhei Vishniakou445af182024-05-13 13:17:05 -0700358 ui::LogicalDisplayId::DEFAULT);
Arpit Singh80fd68a2024-03-26 18:41:06 +0000359 testing::Mock::VerifyAndClearExpectations(testSpotSprite.get());
360}
361
Arpit Singhf4ae0ac2024-03-26 18:41:06 +0000362class PointerControllerSkipScreenshotFlagTest
363 : public PointerControllerTest,
364 public testing::WithParamInterface<PointerControllerInterface::ControllerType> {};
365
366TEST_P(PointerControllerSkipScreenshotFlagTest, updatesSkipScreenshotFlag) {
367 sp<MockSprite> testPointerSprite(new NiceMock<MockSprite>);
368 EXPECT_CALL(*mSpriteController, createSprite).WillOnce(Return(testPointerSprite));
369
370 // Create a pointer controller
371 mPointerController =
372 PointerController::create(mPolicy, mLooper, *mSpriteController, GetParam());
373 ensureDisplayViewportIsSet(ui::LogicalDisplayId::DEFAULT);
374
375 // By default skip screenshot flag is not set for the sprite
376 EXPECT_CALL(*testPointerSprite, setSkipScreenshot).With(testing::Args<0>(false));
377
378 // Update pointer to sync state with sprite
379 mPointerController->setPosition(100, 100);
380 testing::Mock::VerifyAndClearExpectations(testPointerSprite.get());
381
382 // Marking the controller to skip screenshot should update pointer sprite
383 mPointerController->setSkipScreenshotFlagForDisplay(ui::LogicalDisplayId::DEFAULT);
384 EXPECT_CALL(*testPointerSprite, setSkipScreenshot).With(testing::Args<0>(true));
385
386 // Update pointer to sync state with sprite
387 mPointerController->move(10, 10);
388 testing::Mock::VerifyAndClearExpectations(testPointerSprite.get());
389
390 // Reset flag and verify again
391 mPointerController->clearSkipScreenshotFlags();
392 EXPECT_CALL(*testPointerSprite, setSkipScreenshot).With(testing::Args<0>(false));
393 mPointerController->move(10, 10);
394 testing::Mock::VerifyAndClearExpectations(testPointerSprite.get());
395}
396
397INSTANTIATE_TEST_SUITE_P(PointerControllerSkipScreenshotFlagTest,
398 PointerControllerSkipScreenshotFlagTest,
399 testing::Values(PointerControllerInterface::ControllerType::MOUSE,
400 PointerControllerInterface::ControllerType::STYLUS));
401
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800402class PointerControllerWindowInfoListenerTest : public Test {};
403
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800404TEST_F(PointerControllerWindowInfoListenerTest,
405 doesNotCrashIfListenerCalledAfterPointerControllerDestroyed) {
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000406 sp<Looper> looper = new Looper(false);
407 auto spriteController = NiceMock<MockSpriteController>(looper);
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800408 sp<android::gui::WindowInfosListener> registeredListener;
409 sp<android::gui::WindowInfosListener> localListenerCopy;
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700410 sp<MockPointerControllerPolicyInterface> policy = new MockPointerControllerPolicyInterface();
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800411 {
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700412 TestPointerController pointerController(registeredListener, policy, looper,
413 spriteController);
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800414 ASSERT_NE(nullptr, registeredListener) << "WindowInfosListener was not registered";
415 localListenerCopy = registeredListener;
416 }
417 EXPECT_EQ(nullptr, registeredListener) << "WindowInfosListener was not unregistered";
Patrick Williams8e47a672023-05-01 11:30:37 -0500418 localListenerCopy->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800419}
420
Garfield Tanc15eb912019-08-05 16:47:40 -0700421} // namespace android