blob: a1bb5b3f1cc43119a69acd46fa8d6517f35a25a2 [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)
Prabir Pradhanbdf93692024-01-23 18:08:28 +0000164 -> std::vector<gui::DisplayInfo> {
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700165 // Register listener
166 registeredListener = listener;
Linnan Li37c1b992023-11-24 13:05:13 +0800167 return {};
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700168 },
169 [&registeredListener](const sp<android::gui::WindowInfosListener>& listener) {
170 // Unregister listener
171 if (registeredListener == listener) registeredListener = nullptr;
172 }) {}
173 ~TestPointerController() override {}
174};
175
Garfield Tanc15eb912019-08-05 16:47:40 -0700176class PointerControllerTest : public Test {
177protected:
178 PointerControllerTest();
179 ~PointerControllerTest();
180
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000181 void ensureDisplayViewportIsSet(int32_t displayId = ADISPLAY_ID_DEFAULT);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800182
Garfield Tanc15eb912019-08-05 16:47:40 -0700183 sp<MockSprite> mPointerSprite;
184 sp<MockPointerControllerPolicyInterface> mPolicy;
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000185 std::unique_ptr<MockSpriteController> mSpriteController;
Michael Wrighta0bc6b12020-06-26 20:25:34 +0100186 std::shared_ptr<PointerController> mPointerController;
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700187 sp<android::gui::WindowInfosListener> mRegisteredListener;
Garfield Tanc15eb912019-08-05 16:47:40 -0700188
189private:
190 void loopThread();
191
192 std::atomic<bool> mRunning = true;
193 class MyLooper : public Looper {
194 public:
195 MyLooper() : Looper(false) {}
196 ~MyLooper() = default;
197 };
198 sp<MyLooper> mLooper;
199 std::thread mThread;
200};
201
202PointerControllerTest::PointerControllerTest() : mPointerSprite(new NiceMock<MockSprite>),
203 mLooper(new MyLooper), mThread(&PointerControllerTest::loopThread, this) {
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000204 mSpriteController.reset(new NiceMock<MockSpriteController>(mLooper));
Garfield Tanc15eb912019-08-05 16:47:40 -0700205 mPolicy = new MockPointerControllerPolicyInterface();
206
207 EXPECT_CALL(*mSpriteController, createSprite())
208 .WillOnce(Return(mPointerSprite));
209
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700210 mPointerController = std::make_unique<TestPointerController>(mRegisteredListener, mPolicy,
211 mLooper, *mSpriteController);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800212}
Garfield Tanc15eb912019-08-05 16:47:40 -0700213
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800214PointerControllerTest::~PointerControllerTest() {
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700215 mPointerController.reset();
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800216 mRunning.store(false, std::memory_order_relaxed);
217 mThread.join();
218}
219
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000220void PointerControllerTest::ensureDisplayViewportIsSet(int32_t displayId) {
Garfield Tanc15eb912019-08-05 16:47:40 -0700221 DisplayViewport viewport;
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000222 viewport.displayId = displayId;
Garfield Tanc15eb912019-08-05 16:47:40 -0700223 viewport.logicalRight = 1600;
224 viewport.logicalBottom = 1200;
225 viewport.physicalRight = 800;
226 viewport.physicalBottom = 600;
227 viewport.deviceWidth = 400;
228 viewport.deviceHeight = 300;
229 mPointerController->setDisplayViewport(viewport);
Garfield Tanc15eb912019-08-05 16:47:40 -0700230}
231
232void PointerControllerTest::loopThread() {
233 Looper::setForThread(mLooper);
234
235 while (mRunning.load(std::memory_order_relaxed)) {
236 mLooper->pollOnce(100);
237 }
238}
239
240TEST_F(PointerControllerTest, useDefaultCursorTypeByDefault) {
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800241 ensureDisplayViewportIsSet();
Michael Wright6853fe62020-07-02 00:01:38 +0100242 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
Garfield Tanc15eb912019-08-05 16:47:40 -0700243
244 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(CURSOR_TYPE_DEFAULT);
245 EXPECT_CALL(*mPointerSprite, setVisible(true));
246 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
Brandon Pollack015f5d92022-06-02 06:59:33 +0000247 EXPECT_CALL(*mPointerSprite,
248 setIcon(AllOf(Field(&SpriteIcon::style,
249 static_cast<PointerIconStyle>(CURSOR_TYPE_DEFAULT)),
250 Field(&SpriteIcon::hotSpotX, hotspot.first),
251 Field(&SpriteIcon::hotSpotY, hotspot.second))));
Garfield Tanc15eb912019-08-05 16:47:40 -0700252 mPointerController->reloadPointerResources();
253}
254
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900255TEST_F(PointerControllerTest, useStylusTypeForStylusHover) {
256 ensureDisplayViewportIsSet();
257 mPointerController->setPresentation(PointerController::Presentation::STYLUS_HOVER);
258 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
259 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(CURSOR_TYPE_STYLUS);
260 EXPECT_CALL(*mPointerSprite, setVisible(true));
261 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
262 EXPECT_CALL(*mPointerSprite,
263 setIcon(AllOf(Field(&SpriteIcon::style,
264 static_cast<PointerIconStyle>(CURSOR_TYPE_STYLUS)),
265 Field(&SpriteIcon::hotSpotX, hotspot.first),
266 Field(&SpriteIcon::hotSpotY, hotspot.second))));
267 mPointerController->reloadPointerResources();
268}
269
Prabir Pradhan6c7aa6f2023-12-12 16:54:59 +0000270TEST_F_WITH_FLAGS(PointerControllerTest, setPresentationBeforeDisplayViewportDoesNotLoadResources,
271 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(input_flags, enable_pointer_choreographer))) {
272 // Setting the presentation mode before a display viewport is set will not load any resources.
273 mPointerController->setPresentation(PointerController::Presentation::POINTER);
274 ASSERT_TRUE(mPolicy->noResourcesAreLoaded());
275
276 // When the display is set, then the resources are loaded.
277 ensureDisplayViewportIsSet();
278 ASSERT_TRUE(mPolicy->allResourcesAreLoaded());
279}
280
281TEST_F_WITH_FLAGS(PointerControllerTest, updatePointerIcon,
282 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(input_flags,
283 enable_pointer_choreographer))) {
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800284 ensureDisplayViewportIsSet();
Liam Harringtonc782be62020-07-17 19:48:24 +0000285 mPointerController->setPresentation(PointerController::Presentation::POINTER);
Michael Wright6853fe62020-07-02 00:01:38 +0100286 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
Garfield Tanc15eb912019-08-05 16:47:40 -0700287
Garfield Tane9c61512019-11-21 16:42:13 -0800288 int32_t type = CURSOR_TYPE_ADDITIONAL;
Garfield Tanc15eb912019-08-05 16:47:40 -0700289 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(type);
290 EXPECT_CALL(*mPointerSprite, setVisible(true));
291 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
Brandon Pollack015f5d92022-06-02 06:59:33 +0000292 EXPECT_CALL(*mPointerSprite,
293 setIcon(AllOf(Field(&SpriteIcon::style, static_cast<PointerIconStyle>(type)),
294 Field(&SpriteIcon::hotSpotX, hotspot.first),
295 Field(&SpriteIcon::hotSpotY, hotspot.second))));
296 mPointerController->updatePointerIcon(static_cast<PointerIconStyle>(type));
Garfield Tanc15eb912019-08-05 16:47:40 -0700297}
298
Prabir Pradhan6c7aa6f2023-12-12 16:54:59 +0000299TEST_F_WITH_FLAGS(PointerControllerTest, updatePointerIconWithChoreographer,
300 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(input_flags, enable_pointer_choreographer))) {
301 // When PointerChoreographer is enabled, the presentation mode is set before the viewport.
302 mPointerController->setPresentation(PointerController::Presentation::POINTER);
303 ensureDisplayViewportIsSet();
304 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
305
306 int32_t type = CURSOR_TYPE_ADDITIONAL;
307 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(type);
308 EXPECT_CALL(*mPointerSprite, setVisible(true));
309 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
310 EXPECT_CALL(*mPointerSprite,
311 setIcon(AllOf(Field(&SpriteIcon::style, static_cast<PointerIconStyle>(type)),
312 Field(&SpriteIcon::hotSpotX, hotspot.first),
313 Field(&SpriteIcon::hotSpotY, hotspot.second))));
314 mPointerController->updatePointerIcon(static_cast<PointerIconStyle>(type));
315}
316
Garfield Tanc15eb912019-08-05 16:47:40 -0700317TEST_F(PointerControllerTest, setCustomPointerIcon) {
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800318 ensureDisplayViewportIsSet();
Michael Wright6853fe62020-07-02 00:01:38 +0100319 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
Garfield Tanc15eb912019-08-05 16:47:40 -0700320
321 int32_t style = CURSOR_TYPE_CUSTOM;
322 float hotSpotX = 15;
323 float hotSpotY = 20;
324
325 SpriteIcon icon;
Brandon Pollack015f5d92022-06-02 06:59:33 +0000326 icon.style = static_cast<PointerIconStyle>(style);
Garfield Tanc15eb912019-08-05 16:47:40 -0700327 icon.hotSpotX = hotSpotX;
328 icon.hotSpotY = hotSpotY;
329
330 EXPECT_CALL(*mPointerSprite, setVisible(true));
331 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
Brandon Pollack015f5d92022-06-02 06:59:33 +0000332 EXPECT_CALL(*mPointerSprite,
333 setIcon(AllOf(Field(&SpriteIcon::style, static_cast<PointerIconStyle>(style)),
334 Field(&SpriteIcon::hotSpotX, hotSpotX),
335 Field(&SpriteIcon::hotSpotY, hotSpotY))));
Garfield Tanc15eb912019-08-05 16:47:40 -0700336 mPointerController->setCustomPointerIcon(icon);
337}
338
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800339TEST_F(PointerControllerTest, doesNotGetResourcesBeforeSettingViewport) {
Michael Wright6853fe62020-07-02 00:01:38 +0100340 mPointerController->setPresentation(PointerController::Presentation::POINTER);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800341 mPointerController->setPosition(1.0f, 1.0f);
342 mPointerController->move(1.0f, 1.0f);
Michael Wright6853fe62020-07-02 00:01:38 +0100343 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
344 mPointerController->fade(PointerController::Transition::IMMEDIATE);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800345
346 EXPECT_TRUE(mPolicy->noResourcesAreLoaded());
347
348 ensureDisplayViewportIsSet();
349}
350
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000351TEST_F(PointerControllerTest, notifiesPolicyWhenPointerDisplayChanges) {
352 EXPECT_FALSE(mPolicy->getLastReportedPointerDisplayId())
353 << "A pointer display change does not occur when PointerController is created.";
354
355 ensureDisplayViewportIsSet(ADISPLAY_ID_DEFAULT);
356
357 const auto lastReportedPointerDisplayId = mPolicy->getLastReportedPointerDisplayId();
358 ASSERT_TRUE(lastReportedPointerDisplayId)
359 << "The policy is notified of a pointer display change when the viewport is first set.";
360 EXPECT_EQ(ADISPLAY_ID_DEFAULT, *lastReportedPointerDisplayId)
361 << "Incorrect pointer display notified.";
362
363 ensureDisplayViewportIsSet(42);
364
365 EXPECT_EQ(42, *mPolicy->getLastReportedPointerDisplayId())
366 << "The policy is notified when the pointer display changes.";
367
368 // Release the PointerController.
369 mPointerController = nullptr;
370
371 EXPECT_EQ(ADISPLAY_ID_NONE, *mPolicy->getLastReportedPointerDisplayId())
372 << "The pointer display changes to invalid when PointerController is destroyed.";
373}
374
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800375class PointerControllerWindowInfoListenerTest : public Test {};
376
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800377TEST_F(PointerControllerWindowInfoListenerTest,
378 doesNotCrashIfListenerCalledAfterPointerControllerDestroyed) {
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000379 sp<Looper> looper = new Looper(false);
380 auto spriteController = NiceMock<MockSpriteController>(looper);
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800381 sp<android::gui::WindowInfosListener> registeredListener;
382 sp<android::gui::WindowInfosListener> localListenerCopy;
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700383 sp<MockPointerControllerPolicyInterface> policy = new MockPointerControllerPolicyInterface();
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800384 {
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700385 TestPointerController pointerController(registeredListener, policy, looper,
386 spriteController);
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800387 ASSERT_NE(nullptr, registeredListener) << "WindowInfosListener was not registered";
388 localListenerCopy = registeredListener;
389 }
390 EXPECT_EQ(nullptr, registeredListener) << "WindowInfosListener was not unregistered";
Patrick Williams8e47a672023-05-01 11:30:37 -0500391 localListenerCopy->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800392}
393
Garfield Tanc15eb912019-08-05 16:47:40 -0700394} // namespace android