1 /*
2 * Copyright 2022 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 "InputMapperTest.h"
18
19 #include <InputReaderBase.h>
20 #include <gtest/gtest.h>
21 #include <ui/Rotation.h>
22
23 namespace android {
24
25 using testing::Return;
26
SetUp()27 void InputMapperUnitTest::SetUp() {
28 mFakePointerController = std::make_shared<FakePointerController>();
29 mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
30 mFakePointerController->setPosition(400, 240);
31
32 EXPECT_CALL(mMockInputReaderContext, getPointerController(DEVICE_ID))
33 .WillRepeatedly(Return(mFakePointerController));
34
35 EXPECT_CALL(mMockInputReaderContext, getEventHub()).WillRepeatedly(Return(&mMockEventHub));
36 InputDeviceIdentifier identifier;
37 identifier.name = "device";
38 identifier.location = "USB1";
39 identifier.bus = 0;
40
41 EXPECT_CALL(mMockEventHub, getDeviceIdentifier(EVENTHUB_ID)).WillRepeatedly(Return(identifier));
42 mDevice = std::make_unique<InputDevice>(&mMockInputReaderContext, DEVICE_ID,
43 /*generation=*/2, identifier);
44 mDeviceContext = std::make_unique<InputDeviceContext>(*mDevice, EVENTHUB_ID);
45 }
46
setupAxis(int axis,bool valid,int32_t min,int32_t max,int32_t resolution)47 void InputMapperUnitTest::setupAxis(int axis, bool valid, int32_t min, int32_t max,
48 int32_t resolution) {
49 EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis, testing::_))
50 .WillRepeatedly([=](int32_t, int32_t, RawAbsoluteAxisInfo* outAxisInfo) {
51 outAxisInfo->valid = valid;
52 outAxisInfo->minValue = min;
53 outAxisInfo->maxValue = max;
54 outAxisInfo->flat = 0;
55 outAxisInfo->fuzz = 0;
56 outAxisInfo->resolution = resolution;
57 return valid ? OK : -1;
58 });
59 }
60
expectScanCodes(bool present,std::set<int> scanCodes)61 void InputMapperUnitTest::expectScanCodes(bool present, std::set<int> scanCodes) {
62 for (const auto& scanCode : scanCodes) {
63 EXPECT_CALL(mMockEventHub, hasScanCode(EVENTHUB_ID, scanCode))
64 .WillRepeatedly(testing::Return(present));
65 }
66 }
67
setScanCodeState(KeyState state,std::set<int> scanCodes)68 void InputMapperUnitTest::setScanCodeState(KeyState state, std::set<int> scanCodes) {
69 for (const auto& scanCode : scanCodes) {
70 EXPECT_CALL(mMockEventHub, getScanCodeState(EVENTHUB_ID, scanCode))
71 .WillRepeatedly(testing::Return(static_cast<int>(state)));
72 }
73 }
74
setKeyCodeState(KeyState state,std::set<int> keyCodes)75 void InputMapperUnitTest::setKeyCodeState(KeyState state, std::set<int> keyCodes) {
76 for (const auto& keyCode : keyCodes) {
77 EXPECT_CALL(mMockEventHub, getKeyCodeState(EVENTHUB_ID, keyCode))
78 .WillRepeatedly(testing::Return(static_cast<int>(state)));
79 }
80 }
81
process(int32_t type,int32_t code,int32_t value)82 std::list<NotifyArgs> InputMapperUnitTest::process(int32_t type, int32_t code, int32_t value) {
83 RawEvent event;
84 event.when = systemTime(SYSTEM_TIME_MONOTONIC);
85 event.readTime = event.when;
86 event.deviceId = mMapper->getDeviceContext().getEventHubId();
87 event.type = type;
88 event.code = code;
89 event.value = value;
90 return mMapper->process(&event);
91 }
92
93 const char* InputMapperTest::DEVICE_NAME = "device";
94 const char* InputMapperTest::DEVICE_LOCATION = "USB1";
95 const ftl::Flags<InputDeviceClass> InputMapperTest::DEVICE_CLASSES =
96 ftl::Flags<InputDeviceClass>(0); // not needed for current tests
97
SetUp(ftl::Flags<InputDeviceClass> classes,int bus)98 void InputMapperTest::SetUp(ftl::Flags<InputDeviceClass> classes, int bus) {
99 mFakeEventHub = std::make_unique<FakeEventHub>();
100 mFakePolicy = sp<FakeInputReaderPolicy>::make();
101 mFakeListener = std::make_unique<TestInputListener>();
102 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy, *mFakeListener);
103 mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes, bus);
104 // Consume the device reset notification generated when adding a new device.
105 mFakeListener->assertNotifyDeviceResetWasCalled();
106 }
107
SetUp()108 void InputMapperTest::SetUp() {
109 SetUp(DEVICE_CLASSES);
110 }
111
TearDown()112 void InputMapperTest::TearDown() {
113 mFakeListener.reset();
114 mFakePolicy.clear();
115 }
116
addConfigurationProperty(const char * key,const char * value)117 void InputMapperTest::addConfigurationProperty(const char* key, const char* value) {
118 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, key, value);
119 }
120
configureDevice(ConfigurationChanges changes)121 std::list<NotifyArgs> InputMapperTest::configureDevice(ConfigurationChanges changes) {
122 using namespace ftl::flag_operators;
123 if (!changes.any() ||
124 (changes.any(InputReaderConfiguration::Change::DISPLAY_INFO |
125 InputReaderConfiguration::Change::POINTER_CAPTURE |
126 InputReaderConfiguration::Change::DEVICE_TYPE))) {
127 mReader->requestRefreshConfiguration(changes);
128 mReader->loopOnce();
129 }
130 std::list<NotifyArgs> out =
131 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), changes);
132 // Loop the reader to flush the input listener queue.
133 for (const NotifyArgs& args : out) {
134 mFakeListener->notify(args);
135 }
136 mReader->loopOnce();
137 return out;
138 }
139
newDevice(int32_t deviceId,const std::string & name,const std::string & location,int32_t eventHubId,ftl::Flags<InputDeviceClass> classes,int bus)140 std::shared_ptr<InputDevice> InputMapperTest::newDevice(int32_t deviceId, const std::string& name,
141 const std::string& location,
142 int32_t eventHubId,
143 ftl::Flags<InputDeviceClass> classes,
144 int bus) {
145 InputDeviceIdentifier identifier;
146 identifier.name = name;
147 identifier.location = location;
148 identifier.bus = bus;
149 std::shared_ptr<InputDevice> device =
150 std::make_shared<InputDevice>(mReader->getContext(), deviceId, DEVICE_GENERATION,
151 identifier);
152 mReader->pushNextDevice(device);
153 mFakeEventHub->addDevice(eventHubId, name, classes, bus);
154 mReader->loopOnce();
155 return device;
156 }
157
setDisplayInfoAndReconfigure(int32_t displayId,int32_t width,int32_t height,ui::Rotation orientation,const std::string & uniqueId,std::optional<uint8_t> physicalPort,ViewportType viewportType)158 void InputMapperTest::setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
159 ui::Rotation orientation,
160 const std::string& uniqueId,
161 std::optional<uint8_t> physicalPort,
162 ViewportType viewportType) {
163 mFakePolicy->addDisplayViewport(displayId, width, height, orientation, /* isActive= */ true,
164 uniqueId, physicalPort, viewportType);
165 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
166 }
167
clearViewports()168 void InputMapperTest::clearViewports() {
169 mFakePolicy->clearViewports();
170 }
171
process(InputMapper & mapper,nsecs_t when,nsecs_t readTime,int32_t type,int32_t code,int32_t value)172 std::list<NotifyArgs> InputMapperTest::process(InputMapper& mapper, nsecs_t when, nsecs_t readTime,
173 int32_t type, int32_t code, int32_t value) {
174 RawEvent event;
175 event.when = when;
176 event.readTime = readTime;
177 event.deviceId = mapper.getDeviceContext().getEventHubId();
178 event.type = type;
179 event.code = code;
180 event.value = value;
181 std::list<NotifyArgs> processArgList = mapper.process(&event);
182 for (const NotifyArgs& args : processArgList) {
183 mFakeListener->notify(args);
184 }
185 // Loop the reader to flush the input listener queue.
186 mReader->loopOnce();
187 return processArgList;
188 }
189
resetMapper(InputMapper & mapper,nsecs_t when)190 void InputMapperTest::resetMapper(InputMapper& mapper, nsecs_t when) {
191 const auto resetArgs = mapper.reset(when);
192 for (const auto args : resetArgs) {
193 mFakeListener->notify(args);
194 }
195 // Loop the reader to flush the input listener queue.
196 mReader->loopOnce();
197 }
198
handleTimeout(InputMapper & mapper,nsecs_t when)199 std::list<NotifyArgs> InputMapperTest::handleTimeout(InputMapper& mapper, nsecs_t when) {
200 std::list<NotifyArgs> generatedArgs = mapper.timeoutExpired(when);
201 for (const NotifyArgs& args : generatedArgs) {
202 mFakeListener->notify(args);
203 }
204 // Loop the reader to flush the input listener queue.
205 mReader->loopOnce();
206 return generatedArgs;
207 }
208
assertMotionRange(const InputDeviceInfo & info,int32_t axis,uint32_t source,float min,float max,float flat,float fuzz)209 void InputMapperTest::assertMotionRange(const InputDeviceInfo& info, int32_t axis, uint32_t source,
210 float min, float max, float flat, float fuzz) {
211 const InputDeviceInfo::MotionRange* range = info.getMotionRange(axis, source);
212 ASSERT_TRUE(range != nullptr) << "Axis: " << axis << " Source: " << source;
213 ASSERT_EQ(axis, range->axis) << "Axis: " << axis << " Source: " << source;
214 ASSERT_EQ(source, range->source) << "Axis: " << axis << " Source: " << source;
215 ASSERT_NEAR(min, range->min, EPSILON) << "Axis: " << axis << " Source: " << source;
216 ASSERT_NEAR(max, range->max, EPSILON) << "Axis: " << axis << " Source: " << source;
217 ASSERT_NEAR(flat, range->flat, EPSILON) << "Axis: " << axis << " Source: " << source;
218 ASSERT_NEAR(fuzz, range->fuzz, EPSILON) << "Axis: " << axis << " Source: " << source;
219 }
220
assertPointerCoords(const PointerCoords & coords,float x,float y,float pressure,float size,float touchMajor,float touchMinor,float toolMajor,float toolMinor,float orientation,float distance,float scaledAxisEpsilon)221 void InputMapperTest::assertPointerCoords(const PointerCoords& coords, float x, float y,
222 float pressure, float size, float touchMajor,
223 float touchMinor, float toolMajor, float toolMinor,
224 float orientation, float distance,
225 float scaledAxisEpsilon) {
226 ASSERT_NEAR(x, coords.getAxisValue(AMOTION_EVENT_AXIS_X), scaledAxisEpsilon);
227 ASSERT_NEAR(y, coords.getAxisValue(AMOTION_EVENT_AXIS_Y), scaledAxisEpsilon);
228 ASSERT_NEAR(pressure, coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), EPSILON);
229 ASSERT_NEAR(size, coords.getAxisValue(AMOTION_EVENT_AXIS_SIZE), EPSILON);
230 ASSERT_NEAR(touchMajor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR), scaledAxisEpsilon);
231 ASSERT_NEAR(touchMinor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR), scaledAxisEpsilon);
232 ASSERT_NEAR(toolMajor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR), scaledAxisEpsilon);
233 ASSERT_NEAR(toolMinor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR), scaledAxisEpsilon);
234 ASSERT_NEAR(orientation, coords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION), EPSILON);
235 ASSERT_NEAR(distance, coords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE), EPSILON);
236 }
237
238 } // namespace android
239