blob: 45b426bf5c5ea04c4a8f519ddfd0829b8a1a271a [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,
Linnan Li37c1b992023-11-24 13:05:13 +0800163 [&registeredListener](const sp<android::gui::WindowInfosListener>& listener)
164 -> std::pair<std::vector<gui::WindowInfo>,
165 std::vector<gui::DisplayInfo>> {
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700166 // Register listener
167 registeredListener = listener;
Linnan Li37c1b992023-11-24 13:05:13 +0800168 return {};
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700169 },
170 [&registeredListener](const sp<android::gui::WindowInfosListener>& listener) {
171 // Unregister listener
172 if (registeredListener == listener) registeredListener = nullptr;
173 }) {}
174 ~TestPointerController() override {}
175};
176
Garfield Tanc15eb912019-08-05 16:47:40 -0700177class PointerControllerTest : public Test {
178protected:
179 PointerControllerTest();
180 ~PointerControllerTest();
181
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000182 void ensureDisplayViewportIsSet(int32_t displayId = ADISPLAY_ID_DEFAULT);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800183
Garfield Tanc15eb912019-08-05 16:47:40 -0700184 sp<MockSprite> mPointerSprite;
185 sp<MockPointerControllerPolicyInterface> mPolicy;
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000186 std::unique_ptr<MockSpriteController> mSpriteController;
Michael Wrighta0bc6b12020-06-26 20:25:34 +0100187 std::shared_ptr<PointerController> mPointerController;
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700188 sp<android::gui::WindowInfosListener> mRegisteredListener;
Garfield Tanc15eb912019-08-05 16:47:40 -0700189
190private:
191 void loopThread();
192
193 std::atomic<bool> mRunning = true;
194 class MyLooper : public Looper {
195 public:
196 MyLooper() : Looper(false) {}
197 ~MyLooper() = default;
198 };
199 sp<MyLooper> mLooper;
200 std::thread mThread;
201};
202
203PointerControllerTest::PointerControllerTest() : mPointerSprite(new NiceMock<MockSprite>),
204 mLooper(new MyLooper), mThread(&PointerControllerTest::loopThread, this) {
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000205 mSpriteController.reset(new NiceMock<MockSpriteController>(mLooper));
Garfield Tanc15eb912019-08-05 16:47:40 -0700206 mPolicy = new MockPointerControllerPolicyInterface();
207
208 EXPECT_CALL(*mSpriteController, createSprite())
209 .WillOnce(Return(mPointerSprite));
210
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700211 mPointerController = std::make_unique<TestPointerController>(mRegisteredListener, mPolicy,
212 mLooper, *mSpriteController);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800213}
Garfield Tanc15eb912019-08-05 16:47:40 -0700214
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800215PointerControllerTest::~PointerControllerTest() {
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700216 mPointerController.reset();
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800217 mRunning.store(false, std::memory_order_relaxed);
218 mThread.join();
219}
220
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000221void PointerControllerTest::ensureDisplayViewportIsSet(int32_t displayId) {
Garfield Tanc15eb912019-08-05 16:47:40 -0700222 DisplayViewport viewport;
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000223 viewport.displayId = displayId;
Garfield Tanc15eb912019-08-05 16:47:40 -0700224 viewport.logicalRight = 1600;
225 viewport.logicalBottom = 1200;
226 viewport.physicalRight = 800;
227 viewport.physicalBottom = 600;
228 viewport.deviceWidth = 400;
229 viewport.deviceHeight = 300;
230 mPointerController->setDisplayViewport(viewport);
Garfield Tanc15eb912019-08-05 16:47:40 -0700231}
232
233void PointerControllerTest::loopThread() {
234 Looper::setForThread(mLooper);
235
236 while (mRunning.load(std::memory_order_relaxed)) {
237 mLooper->pollOnce(100);
238 }
239}
240
241TEST_F(PointerControllerTest, useDefaultCursorTypeByDefault) {
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800242 ensureDisplayViewportIsSet();
Michael Wright6853fe62020-07-02 00:01:38 +0100243 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
Garfield Tanc15eb912019-08-05 16:47:40 -0700244
245 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(CURSOR_TYPE_DEFAULT);
246 EXPECT_CALL(*mPointerSprite, setVisible(true));
247 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
Brandon Pollack015f5d92022-06-02 06:59:33 +0000248 EXPECT_CALL(*mPointerSprite,
249 setIcon(AllOf(Field(&SpriteIcon::style,
250 static_cast<PointerIconStyle>(CURSOR_TYPE_DEFAULT)),
251 Field(&SpriteIcon::hotSpotX, hotspot.first),
252 Field(&SpriteIcon::hotSpotY, hotspot.second))));
Garfield Tanc15eb912019-08-05 16:47:40 -0700253 mPointerController->reloadPointerResources();
254}
255
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900256TEST_F(PointerControllerTest, useStylusTypeForStylusHover) {
257 ensureDisplayViewportIsSet();
258 mPointerController->setPresentation(PointerController::Presentation::STYLUS_HOVER);
259 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
260 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(CURSOR_TYPE_STYLUS);
261 EXPECT_CALL(*mPointerSprite, setVisible(true));
262 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
263 EXPECT_CALL(*mPointerSprite,
264 setIcon(AllOf(Field(&SpriteIcon::style,
265 static_cast<PointerIconStyle>(CURSOR_TYPE_STYLUS)),
266 Field(&SpriteIcon::hotSpotX, hotspot.first),
267 Field(&SpriteIcon::hotSpotY, hotspot.second))));
268 mPointerController->reloadPointerResources();
269}
270
Prabir Pradhan6c7aa6f2023-12-12 16:54:59 +0000271TEST_F_WITH_FLAGS(PointerControllerTest, setPresentationBeforeDisplayViewportDoesNotLoadResources,
272 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(input_flags, enable_pointer_choreographer))) {
273 // Setting the presentation mode before a display viewport is set will not load any resources.
274 mPointerController->setPresentation(PointerController::Presentation::POINTER);
275 ASSERT_TRUE(mPolicy->noResourcesAreLoaded());
276
277 // When the display is set, then the resources are loaded.
278 ensureDisplayViewportIsSet();
279 ASSERT_TRUE(mPolicy->allResourcesAreLoaded());
280}
281
282TEST_F_WITH_FLAGS(PointerControllerTest, updatePointerIcon,
283 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(input_flags,
284 enable_pointer_choreographer))) {
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800285 ensureDisplayViewportIsSet();
Liam Harringtonc782be62020-07-17 19:48:24 +0000286 mPointerController->setPresentation(PointerController::Presentation::POINTER);
Michael Wright6853fe62020-07-02 00:01:38 +0100287 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
Garfield Tanc15eb912019-08-05 16:47:40 -0700288
Garfield Tane9c61512019-11-21 16:42:13 -0800289 int32_t type = CURSOR_TYPE_ADDITIONAL;
Garfield Tanc15eb912019-08-05 16:47:40 -0700290 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(type);
291 EXPECT_CALL(*mPointerSprite, setVisible(true));
292 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
Brandon Pollack015f5d92022-06-02 06:59:33 +0000293 EXPECT_CALL(*mPointerSprite,
294 setIcon(AllOf(Field(&SpriteIcon::style, static_cast<PointerIconStyle>(type)),
295 Field(&SpriteIcon::hotSpotX, hotspot.first),
296 Field(&SpriteIcon::hotSpotY, hotspot.second))));
297 mPointerController->updatePointerIcon(static_cast<PointerIconStyle>(type));
Garfield Tanc15eb912019-08-05 16:47:40 -0700298}
299
Prabir Pradhan6c7aa6f2023-12-12 16:54:59 +0000300TEST_F_WITH_FLAGS(PointerControllerTest, updatePointerIconWithChoreographer,
301 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(input_flags, enable_pointer_choreographer))) {
302 // When PointerChoreographer is enabled, the presentation mode is set before the viewport.
303 mPointerController->setPresentation(PointerController::Presentation::POINTER);
304 ensureDisplayViewportIsSet();
305 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
306
307 int32_t type = CURSOR_TYPE_ADDITIONAL;
308 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(type);
309 EXPECT_CALL(*mPointerSprite, setVisible(true));
310 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
311 EXPECT_CALL(*mPointerSprite,
312 setIcon(AllOf(Field(&SpriteIcon::style, static_cast<PointerIconStyle>(type)),
313 Field(&SpriteIcon::hotSpotX, hotspot.first),
314 Field(&SpriteIcon::hotSpotY, hotspot.second))));
315 mPointerController->updatePointerIcon(static_cast<PointerIconStyle>(type));
316}
317
Garfield Tanc15eb912019-08-05 16:47:40 -0700318TEST_F(PointerControllerTest, setCustomPointerIcon) {
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800319 ensureDisplayViewportIsSet();
Michael Wright6853fe62020-07-02 00:01:38 +0100320 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
Garfield Tanc15eb912019-08-05 16:47:40 -0700321
322 int32_t style = CURSOR_TYPE_CUSTOM;
323 float hotSpotX = 15;
324 float hotSpotY = 20;
325
326 SpriteIcon icon;
Brandon Pollack015f5d92022-06-02 06:59:33 +0000327 icon.style = static_cast<PointerIconStyle>(style);
Garfield Tanc15eb912019-08-05 16:47:40 -0700328 icon.hotSpotX = hotSpotX;
329 icon.hotSpotY = hotSpotY;
330
331 EXPECT_CALL(*mPointerSprite, setVisible(true));
332 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
Brandon Pollack015f5d92022-06-02 06:59:33 +0000333 EXPECT_CALL(*mPointerSprite,
334 setIcon(AllOf(Field(&SpriteIcon::style, static_cast<PointerIconStyle>(style)),
335 Field(&SpriteIcon::hotSpotX, hotSpotX),
336 Field(&SpriteIcon::hotSpotY, hotSpotY))));
Garfield Tanc15eb912019-08-05 16:47:40 -0700337 mPointerController->setCustomPointerIcon(icon);
338}
339
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800340TEST_F(PointerControllerTest, doesNotGetResourcesBeforeSettingViewport) {
Michael Wright6853fe62020-07-02 00:01:38 +0100341 mPointerController->setPresentation(PointerController::Presentation::POINTER);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800342 mPointerController->setPosition(1.0f, 1.0f);
343 mPointerController->move(1.0f, 1.0f);
Michael Wright6853fe62020-07-02 00:01:38 +0100344 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
345 mPointerController->fade(PointerController::Transition::IMMEDIATE);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800346
347 EXPECT_TRUE(mPolicy->noResourcesAreLoaded());
348
349 ensureDisplayViewportIsSet();
350}
351
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000352TEST_F(PointerControllerTest, notifiesPolicyWhenPointerDisplayChanges) {
353 EXPECT_FALSE(mPolicy->getLastReportedPointerDisplayId())
354 << "A pointer display change does not occur when PointerController is created.";
355
356 ensureDisplayViewportIsSet(ADISPLAY_ID_DEFAULT);
357
358 const auto lastReportedPointerDisplayId = mPolicy->getLastReportedPointerDisplayId();
359 ASSERT_TRUE(lastReportedPointerDisplayId)
360 << "The policy is notified of a pointer display change when the viewport is first set.";
361 EXPECT_EQ(ADISPLAY_ID_DEFAULT, *lastReportedPointerDisplayId)
362 << "Incorrect pointer display notified.";
363
364 ensureDisplayViewportIsSet(42);
365
366 EXPECT_EQ(42, *mPolicy->getLastReportedPointerDisplayId())
367 << "The policy is notified when the pointer display changes.";
368
369 // Release the PointerController.
370 mPointerController = nullptr;
371
372 EXPECT_EQ(ADISPLAY_ID_NONE, *mPolicy->getLastReportedPointerDisplayId())
373 << "The pointer display changes to invalid when PointerController is destroyed.";
374}
375
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800376class PointerControllerWindowInfoListenerTest : public Test {};
377
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800378TEST_F(PointerControllerWindowInfoListenerTest,
379 doesNotCrashIfListenerCalledAfterPointerControllerDestroyed) {
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000380 sp<Looper> looper = new Looper(false);
381 auto spriteController = NiceMock<MockSpriteController>(looper);
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800382 sp<android::gui::WindowInfosListener> registeredListener;
383 sp<android::gui::WindowInfosListener> localListenerCopy;
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700384 sp<MockPointerControllerPolicyInterface> policy = new MockPointerControllerPolicyInterface();
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800385 {
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700386 TestPointerController pointerController(registeredListener, policy, looper,
387 spriteController);
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800388 ASSERT_NE(nullptr, registeredListener) << "WindowInfosListener was not registered";
389 localListenerCopy = registeredListener;
390 }
391 EXPECT_EQ(nullptr, registeredListener) << "WindowInfosListener was not unregistered";
Patrick Williams8e47a672023-05-01 11:30:37 -0500392 localListenerCopy->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800393}
394
Garfield Tanc15eb912019-08-05 16:47:40 -0700395} // namespace android