blob: b36406d6a703a460072bcc4cd9f219e9811358de [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
17#include "mocks/MockSprite.h"
18#include "mocks/MockSpriteController.h"
19
20#include <input/PointerController.h>
21#include <input/SpriteController.h>
22
23#include <atomic>
24#include <gmock/gmock.h>
25#include <gtest/gtest.h>
26#include <thread>
27
28namespace android {
29
30enum TestCursorType {
31 CURSOR_TYPE_DEFAULT = 0,
32 CURSOR_TYPE_HOVER,
33 CURSOR_TYPE_TOUCH,
34 CURSOR_TYPE_ANCHOR,
Garfield Tane9c61512019-11-21 16:42:13 -080035 CURSOR_TYPE_ADDITIONAL,
36 CURSOR_TYPE_ADDITIONAL_ANIM,
Garfield Tanc15eb912019-08-05 16:47:40 -070037 CURSOR_TYPE_CUSTOM = -1,
38};
39
40using ::testing::AllOf;
41using ::testing::Field;
42using ::testing::NiceMock;
43using ::testing::Mock;
44using ::testing::Return;
45using ::testing::Test;
46
47std::pair<float, float> getHotSpotCoordinatesForType(int32_t type) {
48 return std::make_pair(type * 10, type * 10 + 5);
49}
50
51class MockPointerControllerPolicyInterface : public PointerControllerPolicyInterface {
52public:
53 virtual void loadPointerIcon(SpriteIcon* icon, int32_t displayId) override;
54 virtual void loadPointerResources(PointerResources* outResources, int32_t displayId) override;
55 virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
56 std::map<int32_t, PointerAnimation>* outAnimationResources, int32_t displayId) override;
57 virtual int32_t getDefaultPointerIconId() override;
58 virtual int32_t getCustomPointerIconId() override;
59
60private:
61 void loadPointerIconForType(SpriteIcon* icon, int32_t cursorType);
62};
63
64void MockPointerControllerPolicyInterface::loadPointerIcon(SpriteIcon* icon, int32_t) {
65 loadPointerIconForType(icon, CURSOR_TYPE_DEFAULT);
66}
67
68void MockPointerControllerPolicyInterface::loadPointerResources(PointerResources* outResources,
69 int32_t) {
70 loadPointerIconForType(&outResources->spotHover, CURSOR_TYPE_HOVER);
71 loadPointerIconForType(&outResources->spotTouch, CURSOR_TYPE_TOUCH);
72 loadPointerIconForType(&outResources->spotAnchor, CURSOR_TYPE_ANCHOR);
73}
74
75void MockPointerControllerPolicyInterface::loadAdditionalMouseResources(
76 std::map<int32_t, SpriteIcon>* outResources,
77 std::map<int32_t, PointerAnimation>* outAnimationResources,
78 int32_t) {
79 SpriteIcon icon;
80 PointerAnimation anim;
81
Garfield Tane9c61512019-11-21 16:42:13 -080082 // CURSOR_TYPE_ADDITIONAL doesn't have animation resource.
83 int32_t cursorType = CURSOR_TYPE_ADDITIONAL;
84 loadPointerIconForType(&icon, cursorType);
85 (*outResources)[cursorType] = icon;
86
87 // CURSOR_TYPE_ADDITIONAL_ANIM has animation resource.
88 cursorType = CURSOR_TYPE_ADDITIONAL_ANIM;
89 loadPointerIconForType(&icon, cursorType);
90 anim.animationFrames.push_back(icon);
91 anim.durationPerFrame = 10;
92 (*outResources)[cursorType] = icon;
93 (*outAnimationResources)[cursorType] = anim;
Garfield Tanc15eb912019-08-05 16:47:40 -070094}
95
96int32_t MockPointerControllerPolicyInterface::getDefaultPointerIconId() {
97 return CURSOR_TYPE_DEFAULT;
98}
99
100int32_t MockPointerControllerPolicyInterface::getCustomPointerIconId() {
101 return CURSOR_TYPE_CUSTOM;
102}
103
104void MockPointerControllerPolicyInterface::loadPointerIconForType(SpriteIcon* icon, int32_t type) {
105 icon->style = type;
106 std::pair<float, float> hotSpot = getHotSpotCoordinatesForType(type);
107 icon->hotSpotX = hotSpot.first;
108 icon->hotSpotY = hotSpot.second;
109}
110
111class PointerControllerTest : public Test {
112protected:
113 PointerControllerTest();
114 ~PointerControllerTest();
115
116 sp<MockSprite> mPointerSprite;
117 sp<MockPointerControllerPolicyInterface> mPolicy;
118 sp<MockSpriteController> mSpriteController;
119 sp<PointerController> mPointerController;
120
121private:
122 void loopThread();
123
124 std::atomic<bool> mRunning = true;
125 class MyLooper : public Looper {
126 public:
127 MyLooper() : Looper(false) {}
128 ~MyLooper() = default;
129 };
130 sp<MyLooper> mLooper;
131 std::thread mThread;
132};
133
134PointerControllerTest::PointerControllerTest() : mPointerSprite(new NiceMock<MockSprite>),
135 mLooper(new MyLooper), mThread(&PointerControllerTest::loopThread, this) {
136
137 mSpriteController = new NiceMock<MockSpriteController>(mLooper);
138 mPolicy = new MockPointerControllerPolicyInterface();
139
140 EXPECT_CALL(*mSpriteController, createSprite())
141 .WillOnce(Return(mPointerSprite));
142
143 mPointerController = new PointerController(mPolicy, mLooper, mSpriteController);
144
145 DisplayViewport viewport;
146 viewport.displayId = ADISPLAY_ID_DEFAULT;
147 viewport.logicalRight = 1600;
148 viewport.logicalBottom = 1200;
149 viewport.physicalRight = 800;
150 viewport.physicalBottom = 600;
151 viewport.deviceWidth = 400;
152 viewport.deviceHeight = 300;
153 mPointerController->setDisplayViewport(viewport);
154}
155
156PointerControllerTest::~PointerControllerTest() {
157 mRunning.store(false, std::memory_order_relaxed);
158 mThread.join();
159}
160
161void PointerControllerTest::loopThread() {
162 Looper::setForThread(mLooper);
163
164 while (mRunning.load(std::memory_order_relaxed)) {
165 mLooper->pollOnce(100);
166 }
167}
168
169TEST_F(PointerControllerTest, useDefaultCursorTypeByDefault) {
170 mPointerController->unfade(PointerController::TRANSITION_IMMEDIATE);
171
172 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(CURSOR_TYPE_DEFAULT);
173 EXPECT_CALL(*mPointerSprite, setVisible(true));
174 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
175 EXPECT_CALL(*mPointerSprite, setIcon(
176 AllOf(
177 Field(&SpriteIcon::style, CURSOR_TYPE_DEFAULT),
178 Field(&SpriteIcon::hotSpotX, hotspot.first),
179 Field(&SpriteIcon::hotSpotY, hotspot.second))));
180 mPointerController->reloadPointerResources();
181}
182
183TEST_F(PointerControllerTest, updatePointerIcon) {
184 mPointerController->unfade(PointerController::TRANSITION_IMMEDIATE);
185
Garfield Tane9c61512019-11-21 16:42:13 -0800186 int32_t type = CURSOR_TYPE_ADDITIONAL;
Garfield Tanc15eb912019-08-05 16:47:40 -0700187 std::pair<float, float> hotspot = getHotSpotCoordinatesForType(type);
188 EXPECT_CALL(*mPointerSprite, setVisible(true));
189 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
190 EXPECT_CALL(*mPointerSprite, setIcon(
191 AllOf(
192 Field(&SpriteIcon::style, type),
193 Field(&SpriteIcon::hotSpotX, hotspot.first),
194 Field(&SpriteIcon::hotSpotY, hotspot.second))));
195 mPointerController->updatePointerIcon(type);
196}
197
198TEST_F(PointerControllerTest, setCustomPointerIcon) {
199 mPointerController->unfade(PointerController::TRANSITION_IMMEDIATE);
200
201 int32_t style = CURSOR_TYPE_CUSTOM;
202 float hotSpotX = 15;
203 float hotSpotY = 20;
204
205 SpriteIcon icon;
206 icon.style = style;
207 icon.hotSpotX = hotSpotX;
208 icon.hotSpotY = hotSpotY;
209
210 EXPECT_CALL(*mPointerSprite, setVisible(true));
211 EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
212 EXPECT_CALL(*mPointerSprite, setIcon(
213 AllOf(
214 Field(&SpriteIcon::style, style),
215 Field(&SpriteIcon::hotSpotX, hotSpotX),
216 Field(&SpriteIcon::hotSpotY, hotSpotY))));
217 mPointerController->setCustomPointerIcon(icon);
218}
219
220} // namespace android