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