blob: 9574e79f05e94102359ac4e1417067fa5b25bfa4 [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 <com_android_input_flags.h>
18#include <flag_macros.h>
Brandon Pollack015f5d92022-06-02 06:59:33 +000019#include <gmock/gmock.h>
20#include <gtest/gtest.h>
Garfield Tanc15eb912019-08-05 16:47:40 -070021#include <input/PointerController.h>
22#include <input/SpriteController.h>
23
24#include <atomic>
Garfield Tanc15eb912019-08-05 16:47:40 -070025#include <thread>
26
Brandon Pollack015f5d92022-06-02 06:59:33 +000027#include "input/Input.h"
28#include "mocks/MockSprite.h"
29#include "mocks/MockSpriteController.h"
30
Garfield Tanc15eb912019-08-05 16:47:40 -070031namespace android {
32
Prabir Pradhan6c7aa6f2023-12-12 16:54:59 +000033namespace input_flags = com::android::input::flags;
34
Garfield Tanc15eb912019-08-05 16:47:40 -070035enum TestCursorType {
36 CURSOR_TYPE_DEFAULT = 0,
37 CURSOR_TYPE_HOVER,
38 CURSOR_TYPE_TOUCH,
39 CURSOR_TYPE_ANCHOR,
Garfield Tane9c61512019-11-21 16:42:13 -080040 CURSOR_TYPE_ADDITIONAL,
41 CURSOR_TYPE_ADDITIONAL_ANIM,
Seunghwan Choi670b33d2023-01-13 21:12:59 +090042 CURSOR_TYPE_STYLUS,
Garfield Tanc15eb912019-08-05 16:47:40 -070043 CURSOR_TYPE_CUSTOM = -1,
44};
45
46using ::testing::AllOf;
47using ::testing::Field;
Prabir Pradhanca7d7232020-01-31 17:42:34 -080048using ::testing::NiceMock;
Garfield Tanc15eb912019-08-05 16:47:40 -070049using ::testing::Return;
50using ::testing::Test;
51
52std::pair<float, float> getHotSpotCoordinatesForType(int32_t type) {
53 return std::make_pair(type * 10, type * 10 + 5);
54}
55
56class MockPointerControllerPolicyInterface : public PointerControllerPolicyInterface {
57public:
58 virtual void loadPointerIcon(SpriteIcon* icon, int32_t displayId) override;
59 virtual void loadPointerResources(PointerResources* outResources, int32_t displayId) override;
Brandon Pollack015f5d92022-06-02 06:59:33 +000060 virtual void loadAdditionalMouseResources(
61 std::map<PointerIconStyle, SpriteIcon>* outResources,
62 std::map<PointerIconStyle, PointerAnimation>* outAnimationResources,
63 int32_t displayId) override;
64 virtual PointerIconStyle getDefaultPointerIconId() override;
Seunghwan Choi670b33d2023-01-13 21:12:59 +090065 virtual PointerIconStyle getDefaultStylusIconId() override;
Brandon Pollack015f5d92022-06-02 06:59:33 +000066 virtual PointerIconStyle getCustomPointerIconId() override;
Garfield Tanc15eb912019-08-05 16:47:40 -070067
Prabir Pradhanca7d7232020-01-31 17:42:34 -080068 bool allResourcesAreLoaded();
69 bool noResourcesAreLoaded();
70
Garfield Tanc15eb912019-08-05 16:47:40 -070071private:
72 void loadPointerIconForType(SpriteIcon* icon, int32_t cursorType);
Prabir Pradhanca7d7232020-01-31 17:42:34 -080073
74 bool pointerIconLoaded{false};
75 bool pointerResourcesLoaded{false};
76 bool additionalMouseResourcesLoaded{false};
Garfield Tanc15eb912019-08-05 16:47:40 -070077};
78
79void MockPointerControllerPolicyInterface::loadPointerIcon(SpriteIcon* icon, int32_t) {
80 loadPointerIconForType(icon, CURSOR_TYPE_DEFAULT);
Prabir Pradhanca7d7232020-01-31 17:42:34 -080081 pointerIconLoaded = true;
Garfield Tanc15eb912019-08-05 16:47:40 -070082}
83
84void MockPointerControllerPolicyInterface::loadPointerResources(PointerResources* outResources,
85 int32_t) {
86 loadPointerIconForType(&outResources->spotHover, CURSOR_TYPE_HOVER);
87 loadPointerIconForType(&outResources->spotTouch, CURSOR_TYPE_TOUCH);
88 loadPointerIconForType(&outResources->spotAnchor, CURSOR_TYPE_ANCHOR);
Prabir Pradhanca7d7232020-01-31 17:42:34 -080089 pointerResourcesLoaded = true;
Garfield Tanc15eb912019-08-05 16:47:40 -070090}
91
92void MockPointerControllerPolicyInterface::loadAdditionalMouseResources(
Brandon Pollack015f5d92022-06-02 06:59:33 +000093 std::map<PointerIconStyle, SpriteIcon>* outResources,
94 std::map<PointerIconStyle, PointerAnimation>* outAnimationResources, int32_t) {
Garfield Tanc15eb912019-08-05 16:47:40 -070095 SpriteIcon icon;
96 PointerAnimation anim;
97
Garfield Tane9c61512019-11-21 16:42:13 -080098 // CURSOR_TYPE_ADDITIONAL doesn't have animation resource.
99 int32_t cursorType = CURSOR_TYPE_ADDITIONAL;
100 loadPointerIconForType(&icon, cursorType);
Brandon Pollack015f5d92022-06-02 06:59:33 +0000101 (*outResources)[static_cast<PointerIconStyle>(cursorType)] = icon;
Garfield Tane9c61512019-11-21 16:42:13 -0800102
103 // CURSOR_TYPE_ADDITIONAL_ANIM has animation resource.
104 cursorType = CURSOR_TYPE_ADDITIONAL_ANIM;
105 loadPointerIconForType(&icon, cursorType);
106 anim.animationFrames.push_back(icon);
107 anim.durationPerFrame = 10;
Brandon Pollack015f5d92022-06-02 06:59:33 +0000108 (*outResources)[static_cast<PointerIconStyle>(cursorType)] = icon;
109 (*outAnimationResources)[static_cast<PointerIconStyle>(cursorType)] = anim;
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800110
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900111 // CURSOR_TYPE_STYLUS doesn't have animation resource.
112 cursorType = CURSOR_TYPE_STYLUS;
113 loadPointerIconForType(&icon, cursorType);
114 (*outResources)[static_cast<PointerIconStyle>(cursorType)] = icon;
115
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800116 additionalMouseResourcesLoaded = true;
Garfield Tanc15eb912019-08-05 16:47:40 -0700117}
118
Brandon Pollack015f5d92022-06-02 06:59:33 +0000119PointerIconStyle MockPointerControllerPolicyInterface::getDefaultPointerIconId() {
120 return static_cast<PointerIconStyle>(CURSOR_TYPE_DEFAULT);
Garfield Tanc15eb912019-08-05 16:47:40 -0700121}
122
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900123PointerIconStyle MockPointerControllerPolicyInterface::getDefaultStylusIconId() {
124 return static_cast<PointerIconStyle>(CURSOR_TYPE_STYLUS);
125}
126
Brandon Pollack015f5d92022-06-02 06:59:33 +0000127PointerIconStyle MockPointerControllerPolicyInterface::getCustomPointerIconId() {
128 return static_cast<PointerIconStyle>(CURSOR_TYPE_CUSTOM);
Garfield Tanc15eb912019-08-05 16:47:40 -0700129}
130
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800131bool MockPointerControllerPolicyInterface::allResourcesAreLoaded() {
132 return pointerIconLoaded && pointerResourcesLoaded && additionalMouseResourcesLoaded;
133}
134
135bool MockPointerControllerPolicyInterface::noResourcesAreLoaded() {
136 return !(pointerIconLoaded || pointerResourcesLoaded || additionalMouseResourcesLoaded);
137}
138
Garfield Tanc15eb912019-08-05 16:47:40 -0700139void MockPointerControllerPolicyInterface::loadPointerIconForType(SpriteIcon* icon, int32_t type) {
Brandon Pollack015f5d92022-06-02 06:59:33 +0000140 icon->style = static_cast<PointerIconStyle>(type);
Garfield Tanc15eb912019-08-05 16:47:40 -0700141 std::pair<float, float> hotSpot = getHotSpotCoordinatesForType(type);
142 icon->hotSpotX = hotSpot.first;
143 icon->hotSpotY = hotSpot.second;
144}
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000145
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700146class TestPointerController : public PointerController {
147public:
148 TestPointerController(sp<android::gui::WindowInfosListener>& registeredListener,
149 sp<PointerControllerPolicyInterface> policy, const sp<Looper>& looper,
150 SpriteController& spriteController)
151 : PointerController(
152 policy, looper, spriteController,
153 /*enabled=*/true,
Linnan Li37c1b992023-11-24 13:05:13 +0800154 [&registeredListener](const sp<android::gui::WindowInfosListener>& listener)
Prabir Pradhanbdf93692024-01-23 18:08:28 +0000155 -> std::vector<gui::DisplayInfo> {
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700156 // Register listener
157 registeredListener = listener;
Linnan Li37c1b992023-11-24 13:05:13 +0800158 return {};
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700159 },
160 [&registeredListener](const sp<android::gui::WindowInfosListener>& listener) {
161 // Unregister listener
162 if (registeredListener == listener) registeredListener = nullptr;
163 }) {}
164 ~TestPointerController() override {}
165};
166
Garfield Tanc15eb912019-08-05 16:47:40 -0700167class PointerControllerTest : public Test {
168protected:
169 PointerControllerTest();
170 ~PointerControllerTest();
171
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000172 void ensureDisplayViewportIsSet(int32_t displayId = ADISPLAY_ID_DEFAULT);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800173
Garfield Tanc15eb912019-08-05 16:47:40 -0700174 sp<MockSprite> mPointerSprite;
175 sp<MockPointerControllerPolicyInterface> mPolicy;
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000176 std::unique_ptr<MockSpriteController> mSpriteController;
Michael Wrighta0bc6b12020-06-26 20:25:34 +0100177 std::shared_ptr<PointerController> mPointerController;
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700178 sp<android::gui::WindowInfosListener> mRegisteredListener;
Garfield Tanc15eb912019-08-05 16:47:40 -0700179
180private:
181 void loopThread();
182
183 std::atomic<bool> mRunning = true;
184 class MyLooper : public Looper {
185 public:
186 MyLooper() : Looper(false) {}
187 ~MyLooper() = default;
188 };
189 sp<MyLooper> mLooper;
190 std::thread mThread;
191};
192
193PointerControllerTest::PointerControllerTest() : mPointerSprite(new NiceMock<MockSprite>),
194 mLooper(new MyLooper), mThread(&PointerControllerTest::loopThread, this) {
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000195 mSpriteController.reset(new NiceMock<MockSpriteController>(mLooper));
Garfield Tanc15eb912019-08-05 16:47:40 -0700196 mPolicy = new MockPointerControllerPolicyInterface();
197
198 EXPECT_CALL(*mSpriteController, createSprite())
199 .WillOnce(Return(mPointerSprite));
200
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700201 mPointerController = std::make_unique<TestPointerController>(mRegisteredListener, mPolicy,
202 mLooper, *mSpriteController);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800203}
Garfield Tanc15eb912019-08-05 16:47:40 -0700204
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800205PointerControllerTest::~PointerControllerTest() {
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700206 mPointerController.reset();
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800207 mRunning.store(false, std::memory_order_relaxed);
208 mThread.join();
209}
210
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000211void PointerControllerTest::ensureDisplayViewportIsSet(int32_t displayId) {
Garfield Tanc15eb912019-08-05 16:47:40 -0700212 DisplayViewport viewport;
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000213 viewport.displayId = displayId;
Garfield Tanc15eb912019-08-05 16:47:40 -0700214 viewport.logicalRight = 1600;
215 viewport.logicalBottom = 1200;
216 viewport.physicalRight = 800;
217 viewport.physicalBottom = 600;
218 viewport.deviceWidth = 400;
219 viewport.deviceHeight = 300;
220 mPointerController->setDisplayViewport(viewport);
Garfield Tanc15eb912019-08-05 16:47:40 -0700221}
222
223void PointerControllerTest::loopThread() {
224 Looper::setForThread(mLooper);
225
226 while (mRunning.load(std::memory_order_relaxed)) {
227 mLooper->pollOnce(100);
228 }
229}
230
231TEST_F(PointerControllerTest, useDefaultCursorTypeByDefault) {
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800232 ensureDisplayViewportIsSet();
Michael Wright6853fe62020-07-02 00:01:38 +0100233 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
Garfield Tanc15eb912019-08-05 16:47:40 -0700234
235 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(CURSOR_TYPE_DEFAULT);
236 EXPECT_CALL(*mPointerSprite, setVisible(true));
237 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
Brandon Pollack015f5d92022-06-02 06:59:33 +0000238 EXPECT_CALL(*mPointerSprite,
239 setIcon(AllOf(Field(&SpriteIcon::style,
240 static_cast<PointerIconStyle>(CURSOR_TYPE_DEFAULT)),
241 Field(&SpriteIcon::hotSpotX, hotspot.first),
242 Field(&SpriteIcon::hotSpotY, hotspot.second))));
Garfield Tanc15eb912019-08-05 16:47:40 -0700243 mPointerController->reloadPointerResources();
244}
245
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900246TEST_F(PointerControllerTest, useStylusTypeForStylusHover) {
247 ensureDisplayViewportIsSet();
248 mPointerController->setPresentation(PointerController::Presentation::STYLUS_HOVER);
249 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
250 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(CURSOR_TYPE_STYLUS);
251 EXPECT_CALL(*mPointerSprite, setVisible(true));
252 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
253 EXPECT_CALL(*mPointerSprite,
254 setIcon(AllOf(Field(&SpriteIcon::style,
255 static_cast<PointerIconStyle>(CURSOR_TYPE_STYLUS)),
256 Field(&SpriteIcon::hotSpotX, hotspot.first),
257 Field(&SpriteIcon::hotSpotY, hotspot.second))));
258 mPointerController->reloadPointerResources();
259}
260
Prabir Pradhan6c7aa6f2023-12-12 16:54:59 +0000261TEST_F_WITH_FLAGS(PointerControllerTest, setPresentationBeforeDisplayViewportDoesNotLoadResources,
262 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(input_flags, enable_pointer_choreographer))) {
263 // 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
272TEST_F_WITH_FLAGS(PointerControllerTest, updatePointerIcon,
273 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(input_flags,
274 enable_pointer_choreographer))) {
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800275 ensureDisplayViewportIsSet();
Liam Harringtonc782be62020-07-17 19:48:24 +0000276 mPointerController->setPresentation(PointerController::Presentation::POINTER);
Michael Wright6853fe62020-07-02 00:01:38 +0100277 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
Garfield Tanc15eb912019-08-05 16:47:40 -0700278
Garfield Tane9c61512019-11-21 16:42:13 -0800279 int32_t type = CURSOR_TYPE_ADDITIONAL;
Garfield Tanc15eb912019-08-05 16:47:40 -0700280 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(type);
281 EXPECT_CALL(*mPointerSprite, setVisible(true));
282 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
Brandon Pollack015f5d92022-06-02 06:59:33 +0000283 EXPECT_CALL(*mPointerSprite,
284 setIcon(AllOf(Field(&SpriteIcon::style, static_cast<PointerIconStyle>(type)),
285 Field(&SpriteIcon::hotSpotX, hotspot.first),
286 Field(&SpriteIcon::hotSpotY, hotspot.second))));
287 mPointerController->updatePointerIcon(static_cast<PointerIconStyle>(type));
Garfield Tanc15eb912019-08-05 16:47:40 -0700288}
289
Prabir Pradhan6c7aa6f2023-12-12 16:54:59 +0000290TEST_F_WITH_FLAGS(PointerControllerTest, updatePointerIconWithChoreographer,
291 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(input_flags, enable_pointer_choreographer))) {
292 // When PointerChoreographer is enabled, the presentation mode is set before the viewport.
293 mPointerController->setPresentation(PointerController::Presentation::POINTER);
294 ensureDisplayViewportIsSet();
295 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
296
297 int32_t type = CURSOR_TYPE_ADDITIONAL;
298 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(type);
299 EXPECT_CALL(*mPointerSprite, setVisible(true));
300 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
301 EXPECT_CALL(*mPointerSprite,
302 setIcon(AllOf(Field(&SpriteIcon::style, static_cast<PointerIconStyle>(type)),
303 Field(&SpriteIcon::hotSpotX, hotspot.first),
304 Field(&SpriteIcon::hotSpotY, hotspot.second))));
305 mPointerController->updatePointerIcon(static_cast<PointerIconStyle>(type));
306}
307
Garfield Tanc15eb912019-08-05 16:47:40 -0700308TEST_F(PointerControllerTest, setCustomPointerIcon) {
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800309 ensureDisplayViewportIsSet();
Michael Wright6853fe62020-07-02 00:01:38 +0100310 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
Garfield Tanc15eb912019-08-05 16:47:40 -0700311
312 int32_t style = CURSOR_TYPE_CUSTOM;
313 float hotSpotX = 15;
314 float hotSpotY = 20;
315
316 SpriteIcon icon;
Brandon Pollack015f5d92022-06-02 06:59:33 +0000317 icon.style = static_cast<PointerIconStyle>(style);
Garfield Tanc15eb912019-08-05 16:47:40 -0700318 icon.hotSpotX = hotSpotX;
319 icon.hotSpotY = hotSpotY;
320
321 EXPECT_CALL(*mPointerSprite, setVisible(true));
322 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
Brandon Pollack015f5d92022-06-02 06:59:33 +0000323 EXPECT_CALL(*mPointerSprite,
324 setIcon(AllOf(Field(&SpriteIcon::style, static_cast<PointerIconStyle>(style)),
325 Field(&SpriteIcon::hotSpotX, hotSpotX),
326 Field(&SpriteIcon::hotSpotY, hotSpotY))));
Garfield Tanc15eb912019-08-05 16:47:40 -0700327 mPointerController->setCustomPointerIcon(icon);
328}
329
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800330TEST_F(PointerControllerTest, doesNotGetResourcesBeforeSettingViewport) {
Michael Wright6853fe62020-07-02 00:01:38 +0100331 mPointerController->setPresentation(PointerController::Presentation::POINTER);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800332 mPointerController->setPosition(1.0f, 1.0f);
333 mPointerController->move(1.0f, 1.0f);
Michael Wright6853fe62020-07-02 00:01:38 +0100334 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
335 mPointerController->fade(PointerController::Transition::IMMEDIATE);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800336
337 EXPECT_TRUE(mPolicy->noResourcesAreLoaded());
338
339 ensureDisplayViewportIsSet();
340}
341
Arpit Singh80fd68a2024-03-26 18:41:06 +0000342TEST_F(PointerControllerTest, updatesSkipScreenshotFlagForTouchSpots) {
343 ensureDisplayViewportIsSet();
344
345 PointerCoords testSpotCoords;
346 testSpotCoords.clear();
347 testSpotCoords.setAxisValue(AMOTION_EVENT_AXIS_X, 1);
348 testSpotCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, 1);
349 BitSet32 testIdBits;
350 testIdBits.markBit(0);
351 std::array<uint32_t, MAX_POINTER_ID + 1> testIdToIndex;
352
353 sp<MockSprite> testSpotSprite(new NiceMock<MockSprite>);
354
355 // By default sprite is not marked secure
356 EXPECT_CALL(*mSpriteController, createSprite).WillOnce(Return(testSpotSprite));
357 EXPECT_CALL(*testSpotSprite, setSkipScreenshot).With(testing::Args<0>(false));
358
359 // Update spots to sync state with sprite
360 mPointerController->setSpots(&testSpotCoords, testIdToIndex.cbegin(), testIdBits,
361 ADISPLAY_ID_DEFAULT);
362 testing::Mock::VerifyAndClearExpectations(testSpotSprite.get());
363
364 // Marking the display to skip screenshot should update sprite as well
365 mPointerController->setSkipScreenshot(ADISPLAY_ID_DEFAULT, true);
366 EXPECT_CALL(*testSpotSprite, setSkipScreenshot).With(testing::Args<0>(true));
367
368 // Update spots to sync state with sprite
369 mPointerController->setSpots(&testSpotCoords, testIdToIndex.cbegin(), testIdBits,
370 ADISPLAY_ID_DEFAULT);
371 testing::Mock::VerifyAndClearExpectations(testSpotSprite.get());
372
373 // Reset flag and verify again
374 mPointerController->setSkipScreenshot(ADISPLAY_ID_DEFAULT, false);
375 EXPECT_CALL(*testSpotSprite, setSkipScreenshot).With(testing::Args<0>(false));
376 mPointerController->setSpots(&testSpotCoords, testIdToIndex.cbegin(), testIdBits,
377 ADISPLAY_ID_DEFAULT);
378 testing::Mock::VerifyAndClearExpectations(testSpotSprite.get());
379}
380
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800381class PointerControllerWindowInfoListenerTest : public Test {};
382
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800383TEST_F(PointerControllerWindowInfoListenerTest,
384 doesNotCrashIfListenerCalledAfterPointerControllerDestroyed) {
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000385 sp<Looper> looper = new Looper(false);
386 auto spriteController = NiceMock<MockSpriteController>(looper);
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800387 sp<android::gui::WindowInfosListener> registeredListener;
388 sp<android::gui::WindowInfosListener> localListenerCopy;
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700389 sp<MockPointerControllerPolicyInterface> policy = new MockPointerControllerPolicyInterface();
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800390 {
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700391 TestPointerController pointerController(registeredListener, policy, looper,
392 spriteController);
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800393 ASSERT_NE(nullptr, registeredListener) << "WindowInfosListener was not registered";
394 localListenerCopy = registeredListener;
395 }
396 EXPECT_EQ(nullptr, registeredListener) << "WindowInfosListener was not unregistered";
Patrick Williams8e47a672023-05-01 11:30:37 -0500397 localListenerCopy->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800398}
399
Garfield Tanc15eb912019-08-05 16:47:40 -0700400} // namespace android