blob: 80c934a9bd9507f48584b3a0b85f5062e5d0c2c9 [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
Arpit Singh64a70882024-10-25 21:08:08 +000043static constexpr float EPSILON = MotionEvent::ROUNDING_PRECISION;
44
Garfield Tanc15eb912019-08-05 16:47:40 -070045using ::testing::AllOf;
46using ::testing::Field;
Prabir Pradhanca7d7232020-01-31 17:42:34 -080047using ::testing::NiceMock;
Garfield Tanc15eb912019-08-05 16:47:40 -070048using ::testing::Return;
49using ::testing::Test;
50
51std::pair<float, float> getHotSpotCoordinatesForType(int32_t type) {
52 return std::make_pair(type * 10, type * 10 + 5);
53}
54
55class MockPointerControllerPolicyInterface : public PointerControllerPolicyInterface {
56public:
Linnan Li0defadf2024-05-05 19:17:05 +080057 virtual void loadPointerIcon(SpriteIcon* icon, ui::LogicalDisplayId displayId) override;
58 virtual void loadPointerResources(PointerResources* outResources,
59 ui::LogicalDisplayId 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,
Linnan Li0defadf2024-05-05 19:17:05 +080063 ui::LogicalDisplayId displayId) override;
Brandon Pollack015f5d92022-06-02 06:59:33 +000064 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
Linnan Li0defadf2024-05-05 19:17:05 +080079void MockPointerControllerPolicyInterface::loadPointerIcon(SpriteIcon* icon, ui::LogicalDisplayId) {
Garfield Tanc15eb912019-08-05 16:47:40 -070080 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,
Linnan Li0defadf2024-05-05 19:17:05 +080085 ui::LogicalDisplayId) {
Garfield Tanc15eb912019-08-05 16:47:40 -070086 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,
Linnan Li0defadf2024-05-05 19:17:05 +080094 std::map<PointerIconStyle, PointerAnimation>* outAnimationResources, ui::LogicalDisplayId) {
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,
Linnan Li37c1b992023-11-24 13:05:13 +0800153 [&registeredListener](const sp<android::gui::WindowInfosListener>& listener)
Prabir Pradhanbdf93692024-01-23 18:08:28 +0000154 -> std::vector<gui::DisplayInfo> {
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700155 // Register listener
156 registeredListener = listener;
Linnan Li37c1b992023-11-24 13:05:13 +0800157 return {};
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700158 },
159 [&registeredListener](const sp<android::gui::WindowInfosListener>& listener) {
160 // Unregister listener
161 if (registeredListener == listener) registeredListener = nullptr;
162 }) {}
163 ~TestPointerController() override {}
164};
165
Garfield Tanc15eb912019-08-05 16:47:40 -0700166class PointerControllerTest : public Test {
Arpit Singhc2c839d2024-05-31 14:35:37 +0000167private:
168 void loopThread();
169
170 std::atomic<bool> mRunning = true;
171 class MyLooper : public Looper {
172 public:
173 MyLooper() : Looper(false) {}
174 ~MyLooper() = default;
175 };
176
Garfield Tanc15eb912019-08-05 16:47:40 -0700177protected:
178 PointerControllerTest();
179 ~PointerControllerTest();
180
Siarhei Vishniakou445af182024-05-13 13:17:05 -0700181 void ensureDisplayViewportIsSet(ui::LogicalDisplayId displayId = ui::LogicalDisplayId::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;
Arpit Singhc2c839d2024-05-31 14:35:37 +0000188 sp<MyLooper> mLooper;
Garfield Tanc15eb912019-08-05 16:47:40 -0700189
190private:
Garfield Tanc15eb912019-08-05 16:47:40 -0700191 std::thread mThread;
192};
193
Arpit Singhf4ae0ac2024-03-26 18:41:06 +0000194PointerControllerTest::PointerControllerTest()
195 : mPointerSprite(new NiceMock<MockSprite>),
Arpit Singhc2c839d2024-05-31 14:35:37 +0000196 mLooper(new MyLooper),
197 mThread(&PointerControllerTest::loopThread, this) {
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000198 mSpriteController.reset(new NiceMock<MockSpriteController>(mLooper));
Garfield Tanc15eb912019-08-05 16:47:40 -0700199 mPolicy = new MockPointerControllerPolicyInterface();
200
201 EXPECT_CALL(*mSpriteController, createSprite())
202 .WillOnce(Return(mPointerSprite));
203
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700204 mPointerController = std::make_unique<TestPointerController>(mRegisteredListener, mPolicy,
205 mLooper, *mSpriteController);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800206}
Garfield Tanc15eb912019-08-05 16:47:40 -0700207
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800208PointerControllerTest::~PointerControllerTest() {
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700209 mPointerController.reset();
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800210 mRunning.store(false, std::memory_order_relaxed);
211 mThread.join();
212}
213
Linnan Li0defadf2024-05-05 19:17:05 +0800214void PointerControllerTest::ensureDisplayViewportIsSet(ui::LogicalDisplayId displayId) {
Garfield Tanc15eb912019-08-05 16:47:40 -0700215 DisplayViewport viewport;
Prabir Pradhan0e3d6652022-03-10 14:39:46 +0000216 viewport.displayId = displayId;
Garfield Tanc15eb912019-08-05 16:47:40 -0700217 viewport.logicalRight = 1600;
218 viewport.logicalBottom = 1200;
219 viewport.physicalRight = 800;
220 viewport.physicalBottom = 600;
221 viewport.deviceWidth = 400;
222 viewport.deviceHeight = 300;
223 mPointerController->setDisplayViewport(viewport);
Garfield Tanc15eb912019-08-05 16:47:40 -0700224}
225
226void PointerControllerTest::loopThread() {
227 Looper::setForThread(mLooper);
228
229 while (mRunning.load(std::memory_order_relaxed)) {
230 mLooper->pollOnce(100);
231 }
232}
233
234TEST_F(PointerControllerTest, useDefaultCursorTypeByDefault) {
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800235 ensureDisplayViewportIsSet();
Michael Wright6853fe62020-07-02 00:01:38 +0100236 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
Garfield Tanc15eb912019-08-05 16:47:40 -0700237
238 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(CURSOR_TYPE_DEFAULT);
239 EXPECT_CALL(*mPointerSprite, setVisible(true));
240 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
Brandon Pollack015f5d92022-06-02 06:59:33 +0000241 EXPECT_CALL(*mPointerSprite,
242 setIcon(AllOf(Field(&SpriteIcon::style,
243 static_cast<PointerIconStyle>(CURSOR_TYPE_DEFAULT)),
244 Field(&SpriteIcon::hotSpotX, hotspot.first),
245 Field(&SpriteIcon::hotSpotY, hotspot.second))));
Garfield Tanc15eb912019-08-05 16:47:40 -0700246 mPointerController->reloadPointerResources();
247}
248
Seunghwan Choi670b33d2023-01-13 21:12:59 +0900249TEST_F(PointerControllerTest, useStylusTypeForStylusHover) {
250 ensureDisplayViewportIsSet();
251 mPointerController->setPresentation(PointerController::Presentation::STYLUS_HOVER);
252 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
253 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(CURSOR_TYPE_STYLUS);
254 EXPECT_CALL(*mPointerSprite, setVisible(true));
255 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
256 EXPECT_CALL(*mPointerSprite,
257 setIcon(AllOf(Field(&SpriteIcon::style,
258 static_cast<PointerIconStyle>(CURSOR_TYPE_STYLUS)),
259 Field(&SpriteIcon::hotSpotX, hotspot.first),
260 Field(&SpriteIcon::hotSpotY, hotspot.second))));
261 mPointerController->reloadPointerResources();
262}
263
Prabir Pradhan7dff1422024-05-03 23:33:28 +0000264TEST_F(PointerControllerTest, setPresentationBeforeDisplayViewportDoesNotLoadResources) {
Prabir Pradhan6c7aa6f2023-12-12 16:54:59 +0000265 // Setting the presentation mode before a display viewport is set will not load any resources.
266 mPointerController->setPresentation(PointerController::Presentation::POINTER);
267 ASSERT_TRUE(mPolicy->noResourcesAreLoaded());
268
269 // When the display is set, then the resources are loaded.
270 ensureDisplayViewportIsSet();
271 ASSERT_TRUE(mPolicy->allResourcesAreLoaded());
272}
273
Prabir Pradhan7dff1422024-05-03 23:33:28 +0000274TEST_F(PointerControllerTest, updatePointerIconWithChoreographer) {
Prabir Pradhan6c7aa6f2023-12-12 16:54:59 +0000275 // When PointerChoreographer is enabled, the presentation mode is set before the viewport.
276 mPointerController->setPresentation(PointerController::Presentation::POINTER);
277 ensureDisplayViewportIsSet();
278 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
279
280 int32_t type = CURSOR_TYPE_ADDITIONAL;
281 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(type);
282 EXPECT_CALL(*mPointerSprite, setVisible(true));
283 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
284 EXPECT_CALL(*mPointerSprite,
285 setIcon(AllOf(Field(&SpriteIcon::style, static_cast<PointerIconStyle>(type)),
286 Field(&SpriteIcon::hotSpotX, hotspot.first),
287 Field(&SpriteIcon::hotSpotY, hotspot.second))));
288 mPointerController->updatePointerIcon(static_cast<PointerIconStyle>(type));
289}
290
Garfield Tanc15eb912019-08-05 16:47:40 -0700291TEST_F(PointerControllerTest, setCustomPointerIcon) {
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800292 ensureDisplayViewportIsSet();
Michael Wright6853fe62020-07-02 00:01:38 +0100293 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
Garfield Tanc15eb912019-08-05 16:47:40 -0700294
295 int32_t style = CURSOR_TYPE_CUSTOM;
296 float hotSpotX = 15;
297 float hotSpotY = 20;
298
299 SpriteIcon icon;
Brandon Pollack015f5d92022-06-02 06:59:33 +0000300 icon.style = static_cast<PointerIconStyle>(style);
Garfield Tanc15eb912019-08-05 16:47:40 -0700301 icon.hotSpotX = hotSpotX;
302 icon.hotSpotY = hotSpotY;
303
304 EXPECT_CALL(*mPointerSprite, setVisible(true));
305 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
Brandon Pollack015f5d92022-06-02 06:59:33 +0000306 EXPECT_CALL(*mPointerSprite,
307 setIcon(AllOf(Field(&SpriteIcon::style, static_cast<PointerIconStyle>(style)),
308 Field(&SpriteIcon::hotSpotX, hotSpotX),
309 Field(&SpriteIcon::hotSpotY, hotSpotY))));
Garfield Tanc15eb912019-08-05 16:47:40 -0700310 mPointerController->setCustomPointerIcon(icon);
311}
312
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800313TEST_F(PointerControllerTest, doesNotGetResourcesBeforeSettingViewport) {
Michael Wright6853fe62020-07-02 00:01:38 +0100314 mPointerController->setPresentation(PointerController::Presentation::POINTER);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800315 mPointerController->setPosition(1.0f, 1.0f);
316 mPointerController->move(1.0f, 1.0f);
Michael Wright6853fe62020-07-02 00:01:38 +0100317 mPointerController->unfade(PointerController::Transition::IMMEDIATE);
318 mPointerController->fade(PointerController::Transition::IMMEDIATE);
Prabir Pradhanca7d7232020-01-31 17:42:34 -0800319
320 EXPECT_TRUE(mPolicy->noResourcesAreLoaded());
321
322 ensureDisplayViewportIsSet();
323}
324
Arpit Singh80fd68a2024-03-26 18:41:06 +0000325TEST_F(PointerControllerTest, updatesSkipScreenshotFlagForTouchSpots) {
326 ensureDisplayViewportIsSet();
327
328 PointerCoords testSpotCoords;
329 testSpotCoords.clear();
330 testSpotCoords.setAxisValue(AMOTION_EVENT_AXIS_X, 1);
331 testSpotCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, 1);
332 BitSet32 testIdBits;
333 testIdBits.markBit(0);
334 std::array<uint32_t, MAX_POINTER_ID + 1> testIdToIndex;
335
336 sp<MockSprite> testSpotSprite(new NiceMock<MockSprite>);
337
338 // By default sprite is not marked secure
339 EXPECT_CALL(*mSpriteController, createSprite).WillOnce(Return(testSpotSprite));
340 EXPECT_CALL(*testSpotSprite, setSkipScreenshot).With(testing::Args<0>(false));
341
342 // Update spots to sync state with sprite
343 mPointerController->setSpots(&testSpotCoords, testIdToIndex.cbegin(), testIdBits,
Siarhei Vishniakou445af182024-05-13 13:17:05 -0700344 ui::LogicalDisplayId::DEFAULT);
Arpit Singh80fd68a2024-03-26 18:41:06 +0000345 testing::Mock::VerifyAndClearExpectations(testSpotSprite.get());
346
347 // Marking the display to skip screenshot should update sprite as well
Arpit Singhf4ae0ac2024-03-26 18:41:06 +0000348 mPointerController->setSkipScreenshotFlagForDisplay(ui::LogicalDisplayId::DEFAULT);
Arpit Singh80fd68a2024-03-26 18:41:06 +0000349 EXPECT_CALL(*testSpotSprite, setSkipScreenshot).With(testing::Args<0>(true));
350
351 // Update spots to sync state with sprite
352 mPointerController->setSpots(&testSpotCoords, testIdToIndex.cbegin(), testIdBits,
Siarhei Vishniakou445af182024-05-13 13:17:05 -0700353 ui::LogicalDisplayId::DEFAULT);
Arpit Singh80fd68a2024-03-26 18:41:06 +0000354 testing::Mock::VerifyAndClearExpectations(testSpotSprite.get());
355
356 // Reset flag and verify again
Arpit Singhf4ae0ac2024-03-26 18:41:06 +0000357 mPointerController->clearSkipScreenshotFlags();
Arpit Singh80fd68a2024-03-26 18:41:06 +0000358 EXPECT_CALL(*testSpotSprite, setSkipScreenshot).With(testing::Args<0>(false));
359 mPointerController->setSpots(&testSpotCoords, testIdToIndex.cbegin(), testIdBits,
Siarhei Vishniakou445af182024-05-13 13:17:05 -0700360 ui::LogicalDisplayId::DEFAULT);
Arpit Singh80fd68a2024-03-26 18:41:06 +0000361 testing::Mock::VerifyAndClearExpectations(testSpotSprite.get());
362}
363
Arpit Singhf4ae0ac2024-03-26 18:41:06 +0000364class PointerControllerSkipScreenshotFlagTest
365 : public PointerControllerTest,
366 public testing::WithParamInterface<PointerControllerInterface::ControllerType> {};
367
368TEST_P(PointerControllerSkipScreenshotFlagTest, updatesSkipScreenshotFlag) {
369 sp<MockSprite> testPointerSprite(new NiceMock<MockSprite>);
370 EXPECT_CALL(*mSpriteController, createSprite).WillOnce(Return(testPointerSprite));
371
372 // Create a pointer controller
373 mPointerController =
374 PointerController::create(mPolicy, mLooper, *mSpriteController, GetParam());
375 ensureDisplayViewportIsSet(ui::LogicalDisplayId::DEFAULT);
376
377 // By default skip screenshot flag is not set for the sprite
378 EXPECT_CALL(*testPointerSprite, setSkipScreenshot).With(testing::Args<0>(false));
379
380 // Update pointer to sync state with sprite
381 mPointerController->setPosition(100, 100);
382 testing::Mock::VerifyAndClearExpectations(testPointerSprite.get());
383
384 // Marking the controller to skip screenshot should update pointer sprite
385 mPointerController->setSkipScreenshotFlagForDisplay(ui::LogicalDisplayId::DEFAULT);
386 EXPECT_CALL(*testPointerSprite, setSkipScreenshot).With(testing::Args<0>(true));
387
388 // Update pointer to sync state with sprite
389 mPointerController->move(10, 10);
390 testing::Mock::VerifyAndClearExpectations(testPointerSprite.get());
391
392 // Reset flag and verify again
393 mPointerController->clearSkipScreenshotFlags();
394 EXPECT_CALL(*testPointerSprite, setSkipScreenshot).With(testing::Args<0>(false));
395 mPointerController->move(10, 10);
396 testing::Mock::VerifyAndClearExpectations(testPointerSprite.get());
397}
398
399INSTANTIATE_TEST_SUITE_P(PointerControllerSkipScreenshotFlagTest,
400 PointerControllerSkipScreenshotFlagTest,
401 testing::Values(PointerControllerInterface::ControllerType::MOUSE,
402 PointerControllerInterface::ControllerType::STYLUS));
403
Arpit Singh64a70882024-10-25 21:08:08 +0000404class MousePointerControllerTest : public PointerControllerTest {
405protected:
406 MousePointerControllerTest() {
407 sp<MockSprite> testPointerSprite(new NiceMock<MockSprite>);
408 EXPECT_CALL(*mSpriteController, createSprite).WillOnce(Return(testPointerSprite));
409
410 // create a mouse pointer controller
411 mPointerController =
412 PointerController::create(mPolicy, mLooper, *mSpriteController,
413 PointerControllerInterface::ControllerType::MOUSE);
414
415 // set display viewport
416 DisplayViewport viewport;
417 viewport.displayId = ui::LogicalDisplayId::DEFAULT;
418 viewport.logicalRight = 5;
419 viewport.logicalBottom = 5;
420 viewport.physicalRight = 5;
421 viewport.physicalBottom = 5;
422 viewport.deviceWidth = 5;
423 viewport.deviceHeight = 5;
424 mPointerController->setDisplayViewport(viewport);
425 }
426};
427
428struct MousePointerControllerTestParam {
429 vec2 startPosition;
430 vec2 delta;
431 vec2 endPosition;
432 vec2 unconsumedDelta;
433};
434
435class PointerControllerViewportTransitionTest
436 : public MousePointerControllerTest,
437 public testing::WithParamInterface<MousePointerControllerTestParam> {};
438
439TEST_P(PointerControllerViewportTransitionTest, testPointerViewportTransition) {
440 const auto& params = GetParam();
441
442 mPointerController->setPosition(params.startPosition.x, params.startPosition.y);
443 auto unconsumedDelta = mPointerController->move(params.delta.x, params.delta.y);
444
445 auto position = mPointerController->getPosition();
446 EXPECT_NEAR(position.x, params.endPosition.x, EPSILON);
447 EXPECT_NEAR(position.y, params.endPosition.y, EPSILON);
448 EXPECT_NEAR(unconsumedDelta.x, params.unconsumedDelta.x, EPSILON);
449 EXPECT_NEAR(unconsumedDelta.y, params.unconsumedDelta.y, EPSILON);
450}
451
452INSTANTIATE_TEST_SUITE_P(PointerControllerViewportTransitionTest,
453 PointerControllerViewportTransitionTest,
454 testing::Values(
455 // no transition
456 MousePointerControllerTestParam{{2.0f, 2.0f},
457 {2.0f, 2.0f},
458 {4.0f, 4.0f},
459 {0.0f, 0.0f}},
460 // right boundary
461 MousePointerControllerTestParam{{2.0f, 2.0f},
462 {3.0f, 0.0f},
463 {4.0f, 2.0f},
464 {1.0f, 0.0f}},
465 MousePointerControllerTestParam{{2.0f, 2.0f},
466 {3.0f, -1.0f},
467 {4.0f, 1.0f},
468 {1.0f, 0.0f}},
469 MousePointerControllerTestParam{{2.0f, 2.0f},
470 {3.0f, 1.0f},
471 {4.0f, 3.0f},
472 {1.0f, 0.0f}},
473 // left boundary
474 MousePointerControllerTestParam{{2.0f, 2.0f},
475 {-3.0f, 0.0f},
476 {0.0f, 2.0f},
477 {-1.0f, 0.0f}},
478 MousePointerControllerTestParam{{2.0f, 2.0f},
479 {-3.0f, -1.0f},
480 {0.0f, 1.0f},
481 {-1.0f, 0.0f}},
482 MousePointerControllerTestParam{{2.0f, 2.0f},
483 {-3.0f, 1.0f},
484 {0.0f, 3.0f},
485 {-1.0f, 0.0f}},
486 // bottom boundary
487 MousePointerControllerTestParam{{2.0f, 2.0f},
488 {0.0f, 3.0f},
489 {2.0f, 4.0f},
490 {0.0f, 1.0f}},
491 MousePointerControllerTestParam{{2.0f, 2.0f},
492 {-1.0f, 3.0f},
493 {1.0f, 4.0f},
494 {0.0f, 1.0f}},
495 MousePointerControllerTestParam{{2.0f, 2.0f},
496 {1.0f, 3.0f},
497 {3.0f, 4.0f},
498 {0.0f, 1.0f}},
499 // top boundary
500 MousePointerControllerTestParam{{2.0f, 2.0f},
501 {0.0f, -3.0f},
502 {2.0f, 0.0f},
503 {0.0f, -1.0f}},
504 MousePointerControllerTestParam{{2.0f, 2.0f},
505 {-1.0f, -3.0f},
506 {1.0f, 0.0f},
507 {0.0f, -1.0f}},
508 MousePointerControllerTestParam{{2.0f, 2.0f},
509 {1.0f, -3.0f},
510 {3.0f, 0.0f},
511 {0.0f, -1.0f}},
512 // top-left corner
513 MousePointerControllerTestParam{{2.0f, 2.0f},
514 {-3.0f, -3.0f},
515 {0.0f, 0.0f},
516 {-1.0f, -1.0f}},
517 // top-right corner
518 MousePointerControllerTestParam{{2.0f, 2.0f},
519 {3.0f, -3.0f},
520 {4.0f, 0.0f},
521 {1.0f, -1.0f}},
522 // bottom-right corner
523 MousePointerControllerTestParam{{2.0f, 2.0f},
524 {3.0f, 3.0f},
525 {4.0f, 4.0f},
526 {1.0f, 1.0f}},
527 // bottom-left corner
528 MousePointerControllerTestParam{{2.0f, 2.0f},
529 {-3.0f, 3.0f},
530 {0.0f, 4.0f},
531 {-1.0f, 1.0f}}));
532
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800533class PointerControllerWindowInfoListenerTest : public Test {};
534
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800535TEST_F(PointerControllerWindowInfoListenerTest,
536 doesNotCrashIfListenerCalledAfterPointerControllerDestroyed) {
Prabir Pradhan27c6d992023-08-18 19:44:55 +0000537 sp<Looper> looper = new Looper(false);
538 auto spriteController = NiceMock<MockSpriteController>(looper);
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800539 sp<android::gui::WindowInfosListener> registeredListener;
540 sp<android::gui::WindowInfosListener> localListenerCopy;
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700541 sp<MockPointerControllerPolicyInterface> policy = new MockPointerControllerPolicyInterface();
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800542 {
Siarhei Vishniakoua4ea3002023-09-26 18:40:00 -0700543 TestPointerController pointerController(registeredListener, policy, looper,
544 spriteController);
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800545 ASSERT_NE(nullptr, registeredListener) << "WindowInfosListener was not registered";
546 localListenerCopy = registeredListener;
547 }
548 EXPECT_EQ(nullptr, registeredListener) << "WindowInfosListener was not unregistered";
Patrick Williams8e47a672023-05-01 11:30:37 -0500549 localListenerCopy->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan5693cee2021-12-31 06:51:15 -0800550}
551
Garfield Tanc15eb912019-08-05 16:47:40 -0700552} // namespace android