blob: adfa91e96ebb12ad4bfceb1df4e6e3addd7331d0 [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;
Prabir Pradhanb5dadec2023-02-28 17:43:09 +000067 virtual void onPointerDisplayIdChanged(int32_t displayId, const FloatPoint& position) override;
Garfield Tanc15eb912019-08-05 16:47:40 -070068
Prabir Pradhanca7d7232020-01-31 17:42:34 -080069 bool allResourcesAreLoaded();
70 bool noResourcesAreLoaded();
Prabir Pradhan0e3d6652022-03-10 14:39:46 +000071 std::optional<int32_t> getLastReportedPointerDisplayId() { return latestPointerDisplayId; }
Prabir Pradhanca7d7232020-01-31 17:42:34 -080072
Garfield Tanc15eb912019-08-05 16:47:40 -070073private:
74 void loadPointerIconForType(SpriteIcon* icon, int32_t cursorType);
Prabir Pradhanca7d7232020-01-31 17:42:34 -080075
76 bool pointerIconLoaded{false};
77 bool pointerResourcesLoaded{false};
78 bool additionalMouseResourcesLoaded{false};
Prabir Pradhan0e3d6652022-03-10 14:39:46 +000079 std::optional<int32_t /*displayId*/> latestPointerDisplayId;
Garfield Tanc15eb912019-08-05 16:47:40 -070080};
81
82void MockPointerControllerPolicyInterface::loadPointerIcon(SpriteIcon* icon, int32_t) {
83 loadPointerIconForType(icon, CURSOR_TYPE_DEFAULT);
Prabir Pradhanca7d7232020-01-31 17:42:34 -080084 pointerIconLoaded = true;
Garfield Tanc15eb912019-08-05 16:47:40 -070085}
86
87void MockPointerControllerPolicyInterface::loadPointerResources(PointerResources* outResources,
88 int32_t) {
89 loadPointerIconForType(&outResources->spotHover, CURSOR_TYPE_HOVER);
90 loadPointerIconForType(&outResources->spotTouch, CURSOR_TYPE_TOUCH);
91 loadPointerIconForType(&outResources->spotAnchor, CURSOR_TYPE_ANCHOR);
Prabir Pradhanca7d7232020-01-31 17:42:34 -080092 pointerResourcesLoaded = true;
Garfield Tanc15eb912019-08-05 16:47:40 -070093}
94
95void MockPointerControllerPolicyInterface::loadAdditionalMouseResources(
Brandon Pollack015f5d92022-06-02 06:59:33 +000096 std::map<PointerIconStyle, SpriteIcon>* outResources,
97 std::map<PointerIconStyle, PointerAnimation>* outAnimationResources, int32_t) {
Garfield Tanc15eb912019-08-05 16:47:40 -070098 SpriteIcon icon;
99 PointerAnimation anim;
100
Garfield Tane9c61512019-11-21 16:42:13 -0800101 // CURSOR_TYPE_ADDITIONAL doesn't have animation resource.
102 int32_t cursorType = CURSOR_TYPE_ADDITIONAL;
103 loadPointerIconForType(&icon, cursorType);
Brandon Pollack015f5d92022-06-02 06:59:33 +0000104 (*outResources)[static_cast<PointerIconStyle>(cursorType)] = icon;
Garfield Tane9c61512019-11-21 16:42:13 -0800105
106 // CURSOR_TYPE_ADDITIONAL_ANIM has animation resource.
107 cursorType = CURSOR_TYPE_ADDITIONAL_ANIM;
108 loadPointerIconForType(&icon, cursorType);
109 anim.animationFrames.push_back(icon);
110 anim.durationPerFrame = 10;
Brandon Pollack015f5d92022-06-02 06:59:33 +0000111 (*outResources)[static_cast<PointerIconStyle>(cursorType)] = icon;
112 (*outAnimationResources)[static_cast<PointerIconStyle>(cursorType)] = anim;
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800113
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900114 // CURSOR_TYPE_STYLUS doesn't have animation resource.
115 cursorType = CURSOR_TYPE_STYLUS;
116 loadPointerIconForType(&icon, cursorType);
117 (*outResources)[static_cast<PointerIconStyle>(cursorType)] = icon;
118
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800119 additionalMouseResourcesLoaded = true;
Garfield Tanc15eb912019-08-05 16:47:40 -0700120}
121
Brandon Pollack015f5d92022-06-02 06:59:33 +0000122PointerIconStyle MockPointerControllerPolicyInterface::getDefaultPointerIconId() {
123 return static_cast<PointerIconStyle>(CURSOR_TYPE_DEFAULT);
Garfield Tanc15eb912019-08-05 16:47:40 -0700124}
125
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900126PointerIconStyle MockPointerControllerPolicyInterface::getDefaultStylusIconId() {
127 return static_cast<PointerIconStyle>(CURSOR_TYPE_STYLUS);
128}
129
Brandon Pollack015f5d92022-06-02 06:59:33 +0000130PointerIconStyle MockPointerControllerPolicyInterface::getCustomPointerIconId() {
131 return static_cast<PointerIconStyle>(CURSOR_TYPE_CUSTOM);
Garfield Tanc15eb912019-08-05 16:47:40 -0700132}
133
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800134bool MockPointerControllerPolicyInterface::allResourcesAreLoaded() {
135 return pointerIconLoaded && pointerResourcesLoaded && additionalMouseResourcesLoaded;
136}
137
138bool MockPointerControllerPolicyInterface::noResourcesAreLoaded() {
139 return !(pointerIconLoaded || pointerResourcesLoaded || additionalMouseResourcesLoaded);
140}
141
Garfield Tanc15eb912019-08-05 16:47:40 -0700142void MockPointerControllerPolicyInterface::loadPointerIconForType(SpriteIcon* icon, int32_t type) {
Brandon Pollack015f5d92022-06-02 06:59:33 +0000143 icon->style = static_cast<PointerIconStyle>(type);
Garfield Tanc15eb912019-08-05 16:47:40 -0700144 std::pair<float, float> hotSpot = getHotSpotCoordinatesForType(type);
145 icon->hotSpotX = hotSpot.first;
146 icon->hotSpotY = hotSpot.second;
147}
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000148
149void MockPointerControllerPolicyInterface::onPointerDisplayIdChanged(int32_t displayId,
Prabir Pradhanb5dadec2023-02-28 17:43:09 +0000150 const FloatPoint& /*position*/
151) {
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000152 latestPointerDisplayId = displayId;
153}
154
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700155class TestPointerController : public PointerController {
156public:
157 TestPointerController(sp<android::gui::WindowInfosListener>& registeredListener,
158 sp<PointerControllerPolicyInterface> policy, const sp<Looper>& looper,
159 SpriteController& spriteController)
160 : PointerController(
161 policy, looper, spriteController,
162 /*enabled=*/true,
163 [&registeredListener](const sp<android::gui::WindowInfosListener>& listener) {
164 // Register listener
165 registeredListener = listener;
166 },
167 [&registeredListener](const sp<android::gui::WindowInfosListener>& listener) {
168 // Unregister listener
169 if (registeredListener == listener) registeredListener = nullptr;
170 }) {}
171 ~TestPointerController() override {}
172};
173
Garfield Tanc15eb912019-08-05 16:47:40 -0700174class PointerControllerTest : public Test {
175protected:
176 PointerControllerTest();
177 ~PointerControllerTest();
178
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000179 void ensureDisplayViewportIsSet(int32_t displayId = ADISPLAY_ID_DEFAULT);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800180
Garfield Tanc15eb912019-08-05 16:47:40 -0700181 sp<MockSprite> mPointerSprite;
182 sp<MockPointerControllerPolicyInterface> mPolicy;
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000183 std::unique_ptr<MockSpriteController> mSpriteController;
Michael Wrighta0bc6b12020-06-26 20:25:34 +0100184 std::shared_ptr<PointerController> mPointerController;
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700185 sp<android::gui::WindowInfosListener> mRegisteredListener;
Garfield Tanc15eb912019-08-05 16:47:40 -0700186
187private:
188 void loopThread();
189
190 std::atomic<bool> mRunning = true;
191 class MyLooper : public Looper {
192 public:
193 MyLooper() : Looper(false) {}
194 ~MyLooper() = default;
195 };
196 sp<MyLooper> mLooper;
197 std::thread mThread;
198};
199
200PointerControllerTest::PointerControllerTest() : mPointerSprite(new NiceMock<MockSprite>),
201 mLooper(new MyLooper), mThread(&PointerControllerTest::loopThread, this) {
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000202 mSpriteController.reset(new NiceMock<MockSpriteController>(mLooper));
Garfield Tanc15eb912019-08-05 16:47:40 -0700203 mPolicy = new MockPointerControllerPolicyInterface();
204
205 EXPECT_CALL(*mSpriteController, createSprite())
206 .WillOnce(Return(mPointerSprite));
207
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700208 mPointerController = std::make_unique<TestPointerController>(mRegisteredListener, mPolicy,
209 mLooper, *mSpriteController);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800210}
Garfield Tanc15eb912019-08-05 16:47:40 -0700211
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800212PointerControllerTest::~PointerControllerTest() {
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700213 mPointerController.reset();
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800214 mRunning.store(false, std::memory_order_relaxed);
215 mThread.join();
216}
217
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000218void PointerControllerTest::ensureDisplayViewportIsSet(int32_t displayId) {
Garfield Tanc15eb912019-08-05 16:47:40 -0700219 DisplayViewport viewport;
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000220 viewport.displayId = displayId;
Garfield Tanc15eb912019-08-05 16:47:40 -0700221 viewport.logicalRight = 1600;
222 viewport.logicalBottom = 1200;
223 viewport.physicalRight = 800;
224 viewport.physicalBottom = 600;
225 viewport.deviceWidth = 400;
226 viewport.deviceHeight = 300;
227 mPointerController->setDisplayViewport(viewport);
Garfield Tanc15eb912019-08-05 16:47:40 -0700228}
229
230void PointerControllerTest::loopThread() {
231 Looper::setForThread(mLooper);
232
233 while (mRunning.load(std::memory_order_relaxed)) {
234 mLooper->pollOnce(100);
235 }
236}
237
238TEST_F(PointerControllerTest, useDefaultCursorTypeByDefault) {
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800239 ensureDisplayViewportIsSet();
Michael Wright6853fe62020-07-02 00:01:38 +0100240 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
Garfield Tanc15eb912019-08-05 16:47:40 -0700241
242 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(CURSOR_TYPE_DEFAULT);
243 EXPECT_CALL(*mPointerSprite, setVisible(true));
244 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
Brandon Pollack015f5d92022-06-02 06:59:33 +0000245 EXPECT_CALL(*mPointerSprite,
246 setIcon(AllOf(Field(&SpriteIcon::style,
247 static_cast<PointerIconStyle>(CURSOR_TYPE_DEFAULT)),
248 Field(&SpriteIcon::hotSpotX, hotspot.first),
249 Field(&SpriteIcon::hotSpotY, hotspot.second))));
Garfield Tanc15eb912019-08-05 16:47:40 -0700250 mPointerController->reloadPointerResources();
251}
252
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900253TEST_F(PointerControllerTest, useStylusTypeForStylusHover) {
254 ensureDisplayViewportIsSet();
255 mPointerController->setPresentation(PointerController::Presentation::STYLUS_HOVER);
256 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
257 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(CURSOR_TYPE_STYLUS);
258 EXPECT_CALL(*mPointerSprite, setVisible(true));
259 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
260 EXPECT_CALL(*mPointerSprite,
261 setIcon(AllOf(Field(&SpriteIcon::style,
262 static_cast<PointerIconStyle>(CURSOR_TYPE_STYLUS)),
263 Field(&SpriteIcon::hotSpotX, hotspot.first),
264 Field(&SpriteIcon::hotSpotY, hotspot.second))));
265 mPointerController->reloadPointerResources();
266}
267
Prabir Pradhan6c7aa6f2023-12-12 16:54:59 +0000268TEST_F_WITH_FLAGS(PointerControllerTest, setPresentationBeforeDisplayViewportDoesNotLoadResources,
269 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(input_flags, enable_pointer_choreographer))) {
270 // Setting the presentation mode before a display viewport is set will not load any resources.
271 mPointerController->setPresentation(PointerController::Presentation::POINTER);
272 ASSERT_TRUE(mPolicy->noResourcesAreLoaded());
273
274 // When the display is set, then the resources are loaded.
275 ensureDisplayViewportIsSet();
276 ASSERT_TRUE(mPolicy->allResourcesAreLoaded());
277}
278
279TEST_F_WITH_FLAGS(PointerControllerTest, updatePointerIcon,
280 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(input_flags,
281 enable_pointer_choreographer))) {
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800282 ensureDisplayViewportIsSet();
Liam Harringtonc782be62020-07-17 19:48:24 +0000283 mPointerController->setPresentation(PointerController::Presentation::POINTER);
Michael Wright6853fe62020-07-02 00:01:38 +0100284 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
Garfield Tanc15eb912019-08-05 16:47:40 -0700285
Garfield Tane9c61512019-11-21 16:42:13 -0800286 int32_t type = CURSOR_TYPE_ADDITIONAL;
Garfield Tanc15eb912019-08-05 16:47:40 -0700287 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(type);
288 EXPECT_CALL(*mPointerSprite, setVisible(true));
289 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
Brandon Pollack015f5d92022-06-02 06:59:33 +0000290 EXPECT_CALL(*mPointerSprite,
291 setIcon(AllOf(Field(&SpriteIcon::style, static_cast<PointerIconStyle>(type)),
292 Field(&SpriteIcon::hotSpotX, hotspot.first),
293 Field(&SpriteIcon::hotSpotY, hotspot.second))));
294 mPointerController->updatePointerIcon(static_cast<PointerIconStyle>(type));
Garfield Tanc15eb912019-08-05 16:47:40 -0700295}
296
Prabir Pradhan6c7aa6f2023-12-12 16:54:59 +0000297TEST_F_WITH_FLAGS(PointerControllerTest, updatePointerIconWithChoreographer,
298 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(input_flags, enable_pointer_choreographer))) {
299 // When PointerChoreographer is enabled, the presentation mode is set before the viewport.
300 mPointerController->setPresentation(PointerController::Presentation::POINTER);
301 ensureDisplayViewportIsSet();
302 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
303
304 int32_t type = CURSOR_TYPE_ADDITIONAL;
305 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(type);
306 EXPECT_CALL(*mPointerSprite, setVisible(true));
307 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
308 EXPECT_CALL(*mPointerSprite,
309 setIcon(AllOf(Field(&SpriteIcon::style, static_cast<PointerIconStyle>(type)),
310 Field(&SpriteIcon::hotSpotX, hotspot.first),
311 Field(&SpriteIcon::hotSpotY, hotspot.second))));
312 mPointerController->updatePointerIcon(static_cast<PointerIconStyle>(type));
313}
314
Garfield Tanc15eb912019-08-05 16:47:40 -0700315TEST_F(PointerControllerTest, setCustomPointerIcon) {
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800316 ensureDisplayViewportIsSet();
Michael Wright6853fe62020-07-02 00:01:38 +0100317 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
Garfield Tanc15eb912019-08-05 16:47:40 -0700318
319 int32_t style = CURSOR_TYPE_CUSTOM;
320 float hotSpotX = 15;
321 float hotSpotY = 20;
322
323 SpriteIcon icon;
Brandon Pollack015f5d92022-06-02 06:59:33 +0000324 icon.style = static_cast<PointerIconStyle>(style);
Garfield Tanc15eb912019-08-05 16:47:40 -0700325 icon.hotSpotX = hotSpotX;
326 icon.hotSpotY = hotSpotY;
327
328 EXPECT_CALL(*mPointerSprite, setVisible(true));
329 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
Brandon Pollack015f5d92022-06-02 06:59:33 +0000330 EXPECT_CALL(*mPointerSprite,
331 setIcon(AllOf(Field(&SpriteIcon::style, static_cast<PointerIconStyle>(style)),
332 Field(&SpriteIcon::hotSpotX, hotSpotX),
333 Field(&SpriteIcon::hotSpotY, hotSpotY))));
Garfield Tanc15eb912019-08-05 16:47:40 -0700334 mPointerController->setCustomPointerIcon(icon);
335}
336
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800337TEST_F(PointerControllerTest, doesNotGetResourcesBeforeSettingViewport) {
Michael Wright6853fe62020-07-02 00:01:38 +0100338 mPointerController->setPresentation(PointerController::Presentation::POINTER);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800339 mPointerController->setPosition(1.0f, 1.0f);
340 mPointerController->move(1.0f, 1.0f);
Michael Wright6853fe62020-07-02 00:01:38 +0100341 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
342 mPointerController->fade(PointerController::Transition::IMMEDIATE);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800343
344 EXPECT_TRUE(mPolicy->noResourcesAreLoaded());
345
346 ensureDisplayViewportIsSet();
347}
348
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000349TEST_F(PointerControllerTest, notifiesPolicyWhenPointerDisplayChanges) {
350 EXPECT_FALSE(mPolicy->getLastReportedPointerDisplayId())
351 << "A pointer display change does not occur when PointerController is created.";
352
353 ensureDisplayViewportIsSet(ADISPLAY_ID_DEFAULT);
354
355 const auto lastReportedPointerDisplayId = mPolicy->getLastReportedPointerDisplayId();
356 ASSERT_TRUE(lastReportedPointerDisplayId)
357 << "The policy is notified of a pointer display change when the viewport is first set.";
358 EXPECT_EQ(ADISPLAY_ID_DEFAULT, *lastReportedPointerDisplayId)
359 << "Incorrect pointer display notified.";
360
361 ensureDisplayViewportIsSet(42);
362
363 EXPECT_EQ(42, *mPolicy->getLastReportedPointerDisplayId())
364 << "The policy is notified when the pointer display changes.";
365
366 // Release the PointerController.
367 mPointerController = nullptr;
368
369 EXPECT_EQ(ADISPLAY_ID_NONE, *mPolicy->getLastReportedPointerDisplayId())
370 << "The pointer display changes to invalid when PointerController is destroyed.";
371}
372
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800373class PointerControllerWindowInfoListenerTest : public Test {};
374
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800375TEST_F(PointerControllerWindowInfoListenerTest,
376 doesNotCrashIfListenerCalledAfterPointerControllerDestroyed) {
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000377 sp<Looper> looper = new Looper(false);
378 auto spriteController = NiceMock<MockSpriteController>(looper);
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800379 sp<android::gui::WindowInfosListener> registeredListener;
380 sp<android::gui::WindowInfosListener> localListenerCopy;
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700381 sp<MockPointerControllerPolicyInterface> policy = new MockPointerControllerPolicyInterface();
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800382 {
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700383 TestPointerController pointerController(registeredListener, policy, looper,
384 spriteController);
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800385 ASSERT_NE(nullptr, registeredListener) << "WindowInfosListener was not registered";
386 localListenerCopy = registeredListener;
387 }
388 EXPECT_EQ(nullptr, registeredListener) << "WindowInfosListener was not unregistered";
Patrick Williams8e47a672023-05-01 11:30:37 -0500389 localListenerCopy->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800390}
391
Garfield Tanc15eb912019-08-05 16:47:40 -0700392} // namespace android