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