blob: 1ba79a9c71a65242ab94a271c419de1ff77624bb [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 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
Dominik Laskowski2f01d772022-03-23 16:01:29 -070017#include <cinttypes>
18#include <memory>
Harry Cuttsf13161a2023-03-08 14:15:49 +000019#include <optional>
Dominik Laskowski2f01d772022-03-23 16:01:29 -070020
Prabir Pradhan2770d242019-09-02 18:07:11 -070021#include <CursorInputMapper.h>
22#include <InputDevice.h>
23#include <InputMapper.h>
24#include <InputReader.h>
Prabir Pradhan1aed8582019-12-30 11:46:51 -080025#include <InputReaderBase.h>
26#include <InputReaderFactory.h>
Arthur Hung6d5b4b22022-01-21 07:21:10 +000027#include <JoystickInputMapper.h>
Prabir Pradhan2770d242019-09-02 18:07:11 -070028#include <KeyboardInputMapper.h>
29#include <MultiTouchInputMapper.h>
Prabir Pradhan018faea2024-05-08 21:52:54 +000030#include <NotifyArgsBuilders.h>
Chris Ye1dd2e5c2021-04-04 23:12:41 -070031#include <PeripheralController.h>
Chris Yef59a2f42020-10-16 12:55:26 -070032#include <SensorInputMapper.h>
Prabir Pradhan2770d242019-09-02 18:07:11 -070033#include <SingleTouchInputMapper.h>
34#include <SwitchInputMapper.h>
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000035#include <TestEventMatchers.h>
Prabir Pradhan2770d242019-09-02 18:07:11 -070036#include <TestInputListener.h>
37#include <TouchInputMapper.h>
Prabir Pradhan1aed8582019-12-30 11:46:51 -080038#include <UinputDevice.h>
Chris Ye87143712020-11-10 05:05:58 +000039#include <VibratorInputMapper.h>
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070040#include <android-base/thread_annotations.h>
Byoungho Jungda10dd32023-10-06 17:03:45 +090041#include <com_android_input_flags.h>
Michael Wrighta9cf4192022-12-01 23:46:39 +000042#include <ftl/enum.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080043#include <gtest/gtest.h>
Michael Wrighta9cf4192022-12-01 23:46:39 +000044#include <ui/Rotation.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080045
Siarhei Vishniakou21e96e62022-10-27 10:23:37 -070046#include <thread>
Harry Cuttsa5b71292022-11-28 12:56:17 +000047#include "FakeEventHub.h"
Harry Cutts6b5fbc52022-11-28 16:37:43 +000048#include "FakeInputReaderPolicy.h"
Harry Cuttse6512e12022-11-28 18:44:01 +000049#include "InputMapperTest.h"
Harry Cutts144ff542022-11-28 17:41:06 +000050#include "InstrumentedInputReader.h"
Harry Cuttsa5b71292022-11-28 12:56:17 +000051#include "TestConstants.h"
Michael Wrightdde67b82020-10-27 16:09:22 +000052#include "input/DisplayViewport.h"
53#include "input/Input.h"
Michael Wright17db18e2020-06-26 20:51:44 +010054
Michael Wrightd02c5b62014-02-10 15:10:22 -080055namespace android {
56
Dominik Laskowski2f01d772022-03-23 16:01:29 -070057using namespace ftl::flag_operators;
Prabir Pradhan739dca42022-09-09 20:12:01 +000058using testing::AllOf;
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +000059using testing::VariantWith;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070060using std::chrono_literals::operator""ms;
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -080061using std::chrono_literals::operator""s;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070062
Michael Wrightd02c5b62014-02-10 15:10:22 -080063// Arbitrary display properties.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070064static constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhanc13ff082022-09-08 22:03:30 +000065static const std::string DISPLAY_UNIQUE_ID = "local:1";
Linnan Li13bf76a2024-05-05 19:18:02 +080066static constexpr ui::LogicalDisplayId SECONDARY_DISPLAY_ID =
67 ui::LogicalDisplayId{DISPLAY_ID.val() + 1};
arthurhungcc7f9802020-04-30 17:55:40 +080068static constexpr int32_t DISPLAY_WIDTH = 480;
69static constexpr int32_t DISPLAY_HEIGHT = 800;
Linnan Li13bf76a2024-05-05 19:18:02 +080070static constexpr ui::LogicalDisplayId VIRTUAL_DISPLAY_ID = ui::LogicalDisplayId{1};
arthurhungcc7f9802020-04-30 17:55:40 +080071static constexpr int32_t VIRTUAL_DISPLAY_WIDTH = 400;
72static constexpr int32_t VIRTUAL_DISPLAY_HEIGHT = 500;
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -070073static const char* VIRTUAL_DISPLAY_UNIQUE_ID = "virtual:1";
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -070074static constexpr std::optional<uint8_t> NO_PORT = std::nullopt; // no physical port is specified
Michael Wrightd02c5b62014-02-10 15:10:22 -080075
arthurhungcc7f9802020-04-30 17:55:40 +080076static constexpr int32_t FIRST_SLOT = 0;
77static constexpr int32_t SECOND_SLOT = 1;
78static constexpr int32_t THIRD_SLOT = 2;
79static constexpr int32_t INVALID_TRACKING_ID = -1;
80static constexpr int32_t FIRST_TRACKING_ID = 0;
81static constexpr int32_t SECOND_TRACKING_ID = 1;
82static constexpr int32_t THIRD_TRACKING_ID = 2;
Chris Ye3fdbfef2021-01-06 18:45:18 -080083static constexpr int32_t LIGHT_BRIGHTNESS = 0x55000000;
84static constexpr int32_t LIGHT_COLOR = 0x7F448866;
85static constexpr int32_t LIGHT_PLAYER_ID = 2;
arthurhungcc7f9802020-04-30 17:55:40 +080086
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -080087static constexpr int32_t ACTION_POINTER_0_DOWN =
88 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
89static constexpr int32_t ACTION_POINTER_0_UP =
90 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
91static constexpr int32_t ACTION_POINTER_1_DOWN =
92 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
93static constexpr int32_t ACTION_POINTER_1_UP =
94 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
95
Prabir Pradhanb08a0e82023-09-14 22:28:32 +000096static constexpr uint32_t STYLUS_FUSION_SOURCE =
97 AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_BLUETOOTH_STYLUS;
98
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +000099// Minimum timestamp separation between subsequent input events from a Bluetooth device.
100static constexpr nsecs_t MIN_BLUETOOTH_TIMESTAMP_DELTA = ms2ns(4);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +0000101
Byoungho Jungda10dd32023-10-06 17:03:45 +0900102namespace input_flags = com::android::input::flags;
103
Michael Wrightd02c5b62014-02-10 15:10:22 -0800104template<typename T>
105static inline T min(T a, T b) {
106 return a < b ? a : b;
107}
108
109static inline float avg(float x, float y) {
110 return (x + y) / 2;
111}
112
Chris Ye3fdbfef2021-01-06 18:45:18 -0800113// Mapping for light color name and the light color
114const std::unordered_map<std::string, LightColor> LIGHT_COLORS = {{"red", LightColor::RED},
115 {"green", LightColor::GREEN},
116 {"blue", LightColor::BLUE}};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800117
Michael Wrighta9cf4192022-12-01 23:46:39 +0000118static ui::Rotation getInverseRotation(ui::Rotation orientation) {
Prabir Pradhanc14266f2021-05-12 15:56:24 -0700119 switch (orientation) {
Michael Wrighta9cf4192022-12-01 23:46:39 +0000120 case ui::ROTATION_90:
121 return ui::ROTATION_270;
122 case ui::ROTATION_270:
123 return ui::ROTATION_90;
Prabir Pradhanc14266f2021-05-12 15:56:24 -0700124 default:
125 return orientation;
126 }
127}
128
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800129static void assertAxisResolution(MultiTouchInputMapper& mapper, int axis, float resolution) {
130 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +0000131 mapper.populateDeviceInfo(info);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800132
133 const InputDeviceInfo::MotionRange* motionRange =
134 info.getMotionRange(axis, AINPUT_SOURCE_TOUCHSCREEN);
135 ASSERT_NEAR(motionRange->resolution, resolution, EPSILON);
136}
137
138static void assertAxisNotPresent(MultiTouchInputMapper& mapper, int axis) {
139 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +0000140 mapper.populateDeviceInfo(info);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800141
142 const InputDeviceInfo::MotionRange* motionRange =
143 info.getMotionRange(axis, AINPUT_SOURCE_TOUCHSCREEN);
144 ASSERT_EQ(nullptr, motionRange);
145}
146
Siarhei Vishniakou21e96e62022-10-27 10:23:37 -0700147[[maybe_unused]] static void dumpReader(InputReader& reader) {
148 std::string dump;
149 reader.dump(dump);
150 std::istringstream iss(dump);
151 for (std::string line; std::getline(iss, line);) {
152 ALOGE("%s", line.c_str());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -0800153 std::this_thread::sleep_for(1ms);
Siarhei Vishniakou21e96e62022-10-27 10:23:37 -0700154 }
155}
156
Michael Wrightd02c5b62014-02-10 15:10:22 -0800157// --- FakeInputMapper ---
158
159class FakeInputMapper : public InputMapper {
160 uint32_t mSources;
161 int32_t mKeyboardType;
162 int32_t mMetaState;
163 KeyedVector<int32_t, int32_t> mKeyCodeStates;
164 KeyedVector<int32_t, int32_t> mScanCodeStates;
165 KeyedVector<int32_t, int32_t> mSwitchStates;
Philip Junker4af3b3d2021-12-14 10:36:55 +0100166 // fake mapping which would normally come from keyCharacterMap
167 std::unordered_map<int32_t, int32_t> mKeyCodeMapping;
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800168 std::vector<int32_t> mSupportedKeyCodes;
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700169 std::list<NotifyArgs> mProcessResult;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800170
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700171 std::mutex mLock;
172 std::condition_variable mStateChangedCondition;
173 bool mConfigureWasCalled GUARDED_BY(mLock);
174 bool mResetWasCalled GUARDED_BY(mLock);
175 bool mProcessWasCalled GUARDED_BY(mLock);
176 RawEvent mLastEvent GUARDED_BY(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800177
Arthur Hungc23540e2018-11-29 20:42:11 +0800178 std::optional<DisplayViewport> mViewport;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800179public:
Arpit Singh8e6fb252023-04-06 11:49:17 +0000180 FakeInputMapper(InputDeviceContext& deviceContext, const InputReaderConfiguration& readerConfig,
181 uint32_t sources)
182 : InputMapper(deviceContext, readerConfig),
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800183 mSources(sources),
184 mKeyboardType(AINPUT_KEYBOARD_TYPE_NONE),
Michael Wrightd02c5b62014-02-10 15:10:22 -0800185 mMetaState(0),
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800186 mConfigureWasCalled(false),
187 mResetWasCalled(false),
188 mProcessWasCalled(false) {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800189
Chris Yea52ade12020-08-27 16:49:20 -0700190 virtual ~FakeInputMapper() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800191
192 void setKeyboardType(int32_t keyboardType) {
193 mKeyboardType = keyboardType;
194 }
195
196 void setMetaState(int32_t metaState) {
197 mMetaState = metaState;
198 }
199
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700200 // Sets the return value for the `process` call.
201 void setProcessResult(std::list<NotifyArgs> notifyArgs) {
202 mProcessResult.clear();
203 for (auto notifyArg : notifyArgs) {
204 mProcessResult.push_back(notifyArg);
205 }
206 }
207
Michael Wrightd02c5b62014-02-10 15:10:22 -0800208 void assertConfigureWasCalled() {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700209 std::unique_lock<std::mutex> lock(mLock);
210 base::ScopedLockAssertion assumeLocked(mLock);
211 const bool configureCalled =
212 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
213 return mConfigureWasCalled;
214 });
215 if (!configureCalled) {
216 FAIL() << "Expected configure() to have been called.";
217 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800218 mConfigureWasCalled = false;
219 }
220
221 void assertResetWasCalled() {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700222 std::unique_lock<std::mutex> lock(mLock);
223 base::ScopedLockAssertion assumeLocked(mLock);
224 const bool resetCalled =
225 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
226 return mResetWasCalled;
227 });
228 if (!resetCalled) {
229 FAIL() << "Expected reset() to have been called.";
230 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800231 mResetWasCalled = false;
232 }
233
Prabir Pradhanf8d9e442023-12-06 22:06:13 +0000234 void assertResetWasNotCalled() {
235 std::scoped_lock lock(mLock);
236 ASSERT_FALSE(mResetWasCalled) << "Expected reset to not have been called.";
237 }
238
Yi Kong9b14ac62018-07-17 13:48:38 -0700239 void assertProcessWasCalled(RawEvent* outLastEvent = nullptr) {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700240 std::unique_lock<std::mutex> lock(mLock);
241 base::ScopedLockAssertion assumeLocked(mLock);
242 const bool processCalled =
243 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
244 return mProcessWasCalled;
245 });
246 if (!processCalled) {
247 FAIL() << "Expected process() to have been called.";
248 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800249 if (outLastEvent) {
250 *outLastEvent = mLastEvent;
251 }
252 mProcessWasCalled = false;
253 }
254
Prabir Pradhanf8d9e442023-12-06 22:06:13 +0000255 void assertProcessWasNotCalled() {
256 std::scoped_lock lock(mLock);
257 ASSERT_FALSE(mProcessWasCalled) << "Expected process to not have been called.";
258 }
259
Michael Wrightd02c5b62014-02-10 15:10:22 -0800260 void setKeyCodeState(int32_t keyCode, int32_t state) {
261 mKeyCodeStates.replaceValueFor(keyCode, state);
262 }
263
264 void setScanCodeState(int32_t scanCode, int32_t state) {
265 mScanCodeStates.replaceValueFor(scanCode, state);
266 }
267
268 void setSwitchState(int32_t switchCode, int32_t state) {
269 mSwitchStates.replaceValueFor(switchCode, state);
270 }
271
272 void addSupportedKeyCode(int32_t keyCode) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800273 mSupportedKeyCodes.push_back(keyCode);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800274 }
275
Philip Junker4af3b3d2021-12-14 10:36:55 +0100276 void addKeyCodeMapping(int32_t fromKeyCode, int32_t toKeyCode) {
277 mKeyCodeMapping.insert_or_assign(fromKeyCode, toKeyCode);
278 }
279
Michael Wrightd02c5b62014-02-10 15:10:22 -0800280private:
Philip Junker4af3b3d2021-12-14 10:36:55 +0100281 uint32_t getSources() const override { return mSources; }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800282
Harry Cuttsd02ea102023-03-17 18:21:30 +0000283 void populateDeviceInfo(InputDeviceInfo& deviceInfo) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800284 InputMapper::populateDeviceInfo(deviceInfo);
285
286 if (mKeyboardType != AINPUT_KEYBOARD_TYPE_NONE) {
Harry Cuttsd02ea102023-03-17 18:21:30 +0000287 deviceInfo.setKeyboardType(mKeyboardType);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800288 }
289 }
290
Arpit Singhed6c3de2023-04-05 19:24:37 +0000291 std::list<NotifyArgs> reconfigure(nsecs_t, const InputReaderConfiguration& config,
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000292 ConfigurationChanges changes) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700293 std::scoped_lock<std::mutex> lock(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800294 mConfigureWasCalled = true;
Arthur Hungc23540e2018-11-29 20:42:11 +0800295
296 // Find the associated viewport if exist.
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800297 const std::optional<uint8_t> displayPort = getDeviceContext().getAssociatedDisplayPort();
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000298 if (displayPort && changes.test(InputReaderConfiguration::Change::DISPLAY_INFO)) {
Arpit Singhed6c3de2023-04-05 19:24:37 +0000299 mViewport = config.getDisplayViewportByPort(*displayPort);
Arthur Hungc23540e2018-11-29 20:42:11 +0800300 }
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700301
302 mStateChangedCondition.notify_all();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700303 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800304 }
305
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700306 std::list<NotifyArgs> reset(nsecs_t) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700307 std::scoped_lock<std::mutex> lock(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800308 mResetWasCalled = true;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700309 mStateChangedCondition.notify_all();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700310 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800311 }
312
Harry Cuttsa32a1192024-06-04 15:10:31 +0000313 std::list<NotifyArgs> process(const RawEvent& rawEvent) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700314 std::scoped_lock<std::mutex> lock(mLock);
Harry Cuttsa32a1192024-06-04 15:10:31 +0000315 mLastEvent = rawEvent;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800316 mProcessWasCalled = true;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700317 mStateChangedCondition.notify_all();
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700318 return mProcessResult;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800319 }
320
Chris Yea52ade12020-08-27 16:49:20 -0700321 int32_t getKeyCodeState(uint32_t, int32_t keyCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800322 ssize_t index = mKeyCodeStates.indexOfKey(keyCode);
323 return index >= 0 ? mKeyCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
324 }
325
Philip Junker4af3b3d2021-12-14 10:36:55 +0100326 int32_t getKeyCodeForKeyLocation(int32_t locationKeyCode) const override {
327 auto it = mKeyCodeMapping.find(locationKeyCode);
328 return it != mKeyCodeMapping.end() ? it->second : locationKeyCode;
329 }
330
Chris Yea52ade12020-08-27 16:49:20 -0700331 int32_t getScanCodeState(uint32_t, int32_t scanCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800332 ssize_t index = mScanCodeStates.indexOfKey(scanCode);
333 return index >= 0 ? mScanCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
334 }
335
Chris Yea52ade12020-08-27 16:49:20 -0700336 int32_t getSwitchState(uint32_t, int32_t switchCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800337 ssize_t index = mSwitchStates.indexOfKey(switchCode);
338 return index >= 0 ? mSwitchStates.valueAt(index) : AKEY_STATE_UNKNOWN;
339 }
340
Chris Yea52ade12020-08-27 16:49:20 -0700341 // Return true if the device has non-empty key layout.
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700342 bool markSupportedKeyCodes(uint32_t, const std::vector<int32_t>& keyCodes,
Chris Yea52ade12020-08-27 16:49:20 -0700343 uint8_t* outFlags) override {
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700344 for (size_t i = 0; i < keyCodes.size(); i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800345 for (size_t j = 0; j < mSupportedKeyCodes.size(); j++) {
346 if (keyCodes[i] == mSupportedKeyCodes[j]) {
347 outFlags[i] = 1;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800348 }
349 }
350 }
Chris Yea52ade12020-08-27 16:49:20 -0700351 bool result = mSupportedKeyCodes.size() > 0;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800352 return result;
353 }
354
355 virtual int32_t getMetaState() {
356 return mMetaState;
357 }
358
359 virtual void fadePointer() {
360 }
Arthur Hungc23540e2018-11-29 20:42:11 +0800361
Linnan Li13bf76a2024-05-05 19:18:02 +0800362 virtual std::optional<ui::LogicalDisplayId> getAssociatedDisplay() {
Arthur Hungc23540e2018-11-29 20:42:11 +0800363 if (mViewport) {
364 return std::make_optional(mViewport->displayId);
365 }
366 return std::nullopt;
367 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800368};
369
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700370// --- InputReaderPolicyTest ---
371class InputReaderPolicyTest : public testing::Test {
Siarhei Vishniakoucd7ac1e2018-10-15 13:39:50 -0700372protected:
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700373 sp<FakeInputReaderPolicy> mFakePolicy;
374
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700375 void SetUp() override { mFakePolicy = sp<FakeInputReaderPolicy>::make(); }
Chris Yea52ade12020-08-27 16:49:20 -0700376 void TearDown() override { mFakePolicy.clear(); }
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700377};
378
379/**
380 * Check that empty set of viewports is an acceptable configuration.
381 * Also try to get internal viewport two different ways - by type and by uniqueId.
382 *
383 * There will be confusion if two viewports with empty uniqueId and identical type are present.
384 * Such configuration is not currently allowed.
385 */
386TEST_F(InputReaderPolicyTest, Viewports_GetCleared) {
Siarhei Vishniakoucd7ac1e2018-10-15 13:39:50 -0700387 static const std::string uniqueId = "local:0";
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700388
389 // We didn't add any viewports yet, so there shouldn't be any.
390 std::optional<DisplayViewport> internalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100391 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700392 ASSERT_FALSE(internalViewport);
393
394 // Add an internal viewport, then clear it
Michael Wrighta9cf4192022-12-01 23:46:39 +0000395 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000396 /*isActive=*/true, uniqueId, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700397
398 // Check matching by uniqueId
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700399 internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700400 ASSERT_TRUE(internalViewport);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100401 ASSERT_EQ(ViewportType::INTERNAL, internalViewport->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700402
403 // Check matching by viewport type
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100404 internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700405 ASSERT_TRUE(internalViewport);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700406 ASSERT_EQ(uniqueId, internalViewport->uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700407
408 mFakePolicy->clearViewports();
409 // Make sure nothing is found after clear
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700410 internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700411 ASSERT_FALSE(internalViewport);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100412 internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700413 ASSERT_FALSE(internalViewport);
414}
415
416TEST_F(InputReaderPolicyTest, Viewports_GetByType) {
417 const std::string internalUniqueId = "local:0";
418 const std::string externalUniqueId = "local:1";
419 const std::string virtualUniqueId1 = "virtual:2";
420 const std::string virtualUniqueId2 = "virtual:3";
Linnan Li13bf76a2024-05-05 19:18:02 +0800421 constexpr ui::LogicalDisplayId virtualDisplayId1 = ui::LogicalDisplayId{2};
422 constexpr ui::LogicalDisplayId virtualDisplayId2 = ui::LogicalDisplayId{3};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700423
424 // Add an internal viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000425 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000426 /*isActive=*/true, internalUniqueId, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000427 ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700428 // Add an external viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000429 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000430 /*isActive=*/true, externalUniqueId, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000431 ViewportType::EXTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700432 // Add an virtual viewport
433 mFakePolicy->addDisplayViewport(virtualDisplayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000434 ui::ROTATION_0, /*isActive=*/true, virtualUniqueId1, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000435 ViewportType::VIRTUAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700436 // Add another virtual viewport
437 mFakePolicy->addDisplayViewport(virtualDisplayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000438 ui::ROTATION_0, /*isActive=*/true, virtualUniqueId2, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000439 ViewportType::VIRTUAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700440
441 // Check matching by type for internal
442 std::optional<DisplayViewport> internalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100443 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700444 ASSERT_TRUE(internalViewport);
445 ASSERT_EQ(internalUniqueId, internalViewport->uniqueId);
446
447 // Check matching by type for external
448 std::optional<DisplayViewport> externalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100449 mFakePolicy->getDisplayViewportByType(ViewportType::EXTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700450 ASSERT_TRUE(externalViewport);
451 ASSERT_EQ(externalUniqueId, externalViewport->uniqueId);
452
453 // Check matching by uniqueId for virtual viewport #1
454 std::optional<DisplayViewport> virtualViewport1 =
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700455 mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId1);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700456 ASSERT_TRUE(virtualViewport1);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100457 ASSERT_EQ(ViewportType::VIRTUAL, virtualViewport1->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700458 ASSERT_EQ(virtualUniqueId1, virtualViewport1->uniqueId);
459 ASSERT_EQ(virtualDisplayId1, virtualViewport1->displayId);
460
461 // Check matching by uniqueId for virtual viewport #2
462 std::optional<DisplayViewport> virtualViewport2 =
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700463 mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId2);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700464 ASSERT_TRUE(virtualViewport2);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100465 ASSERT_EQ(ViewportType::VIRTUAL, virtualViewport2->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700466 ASSERT_EQ(virtualUniqueId2, virtualViewport2->uniqueId);
467 ASSERT_EQ(virtualDisplayId2, virtualViewport2->displayId);
468}
469
470
471/**
472 * We can have 2 viewports of the same kind. We can distinguish them by uniqueId, and confirm
473 * that lookup works by checking display id.
474 * Check that 2 viewports of each kind is possible, for all existing viewport types.
475 */
476TEST_F(InputReaderPolicyTest, Viewports_TwoOfSameType) {
477 const std::string uniqueId1 = "uniqueId1";
478 const std::string uniqueId2 = "uniqueId2";
Linnan Li13bf76a2024-05-05 19:18:02 +0800479 constexpr ui::LogicalDisplayId displayId1 = ui::LogicalDisplayId{2};
480 constexpr ui::LogicalDisplayId displayId2 = ui::LogicalDisplayId{3};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700481
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100482 std::vector<ViewportType> types = {ViewportType::INTERNAL, ViewportType::EXTERNAL,
483 ViewportType::VIRTUAL};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700484 for (const ViewportType& type : types) {
485 mFakePolicy->clearViewports();
486 // Add a viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000487 mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000488 /*isActive=*/true, uniqueId1, NO_PORT, type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700489 // Add another viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000490 mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000491 /*isActive=*/true, uniqueId2, NO_PORT, type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700492
493 // Check that correct display viewport was returned by comparing the display IDs.
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700494 std::optional<DisplayViewport> viewport1 =
495 mFakePolicy->getDisplayViewportByUniqueId(uniqueId1);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700496 ASSERT_TRUE(viewport1);
497 ASSERT_EQ(displayId1, viewport1->displayId);
498 ASSERT_EQ(type, viewport1->type);
499
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700500 std::optional<DisplayViewport> viewport2 =
501 mFakePolicy->getDisplayViewportByUniqueId(uniqueId2);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700502 ASSERT_TRUE(viewport2);
503 ASSERT_EQ(displayId2, viewport2->displayId);
504 ASSERT_EQ(type, viewport2->type);
505
506 // When there are multiple viewports of the same kind, and uniqueId is not specified
507 // in the call to getDisplayViewport, then that situation is not supported.
508 // The viewports can be stored in any order, so we cannot rely on the order, since that
509 // is just implementation detail.
510 // However, we can check that it still returns *a* viewport, we just cannot assert
511 // which one specifically is returned.
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700512 std::optional<DisplayViewport> someViewport = mFakePolicy->getDisplayViewportByType(type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700513 ASSERT_TRUE(someViewport);
514 }
515}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800516
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700517/**
Michael Wrightdde67b82020-10-27 16:09:22 +0000518 * When we have multiple internal displays make sure we always return the default display when
519 * querying by type.
520 */
521TEST_F(InputReaderPolicyTest, Viewports_ByTypeReturnsDefaultForInternal) {
522 const std::string uniqueId1 = "uniqueId1";
523 const std::string uniqueId2 = "uniqueId2";
Linnan Li13bf76a2024-05-05 19:18:02 +0800524 constexpr ui::LogicalDisplayId nonDefaultDisplayId = ui::LogicalDisplayId{2};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700525 ASSERT_NE(nonDefaultDisplayId, ui::LogicalDisplayId::DEFAULT)
526 << "Test display ID should not be ui::LogicalDisplayId::DEFAULT ";
Michael Wrightdde67b82020-10-27 16:09:22 +0000527
528 // Add the default display first and ensure it gets returned.
529 mFakePolicy->clearViewports();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700530 mFakePolicy->addDisplayViewport(ui::LogicalDisplayId::DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000531 ui::ROTATION_0, /*isActive=*/true, uniqueId1, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000532 ViewportType::INTERNAL);
533 mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000534 ui::ROTATION_0, /*isActive=*/true, uniqueId2, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000535 ViewportType::INTERNAL);
536
537 std::optional<DisplayViewport> viewport =
538 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
539 ASSERT_TRUE(viewport);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700540 ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, viewport->displayId);
Michael Wrightdde67b82020-10-27 16:09:22 +0000541 ASSERT_EQ(ViewportType::INTERNAL, viewport->type);
542
543 // Add the default display second to make sure order doesn't matter.
544 mFakePolicy->clearViewports();
545 mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000546 ui::ROTATION_0, /*isActive=*/true, uniqueId2, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000547 ViewportType::INTERNAL);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700548 mFakePolicy->addDisplayViewport(ui::LogicalDisplayId::DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000549 ui::ROTATION_0, /*isActive=*/true, uniqueId1, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000550 ViewportType::INTERNAL);
551
552 viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
553 ASSERT_TRUE(viewport);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700554 ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, viewport->displayId);
Michael Wrightdde67b82020-10-27 16:09:22 +0000555 ASSERT_EQ(ViewportType::INTERNAL, viewport->type);
556}
557
558/**
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700559 * Check getDisplayViewportByPort
560 */
561TEST_F(InputReaderPolicyTest, Viewports_GetByPort) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100562 constexpr ViewportType type = ViewportType::EXTERNAL;
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700563 const std::string uniqueId1 = "uniqueId1";
564 const std::string uniqueId2 = "uniqueId2";
Linnan Li13bf76a2024-05-05 19:18:02 +0800565 constexpr ui::LogicalDisplayId displayId1 = ui::LogicalDisplayId{1};
566 constexpr ui::LogicalDisplayId displayId2 = ui::LogicalDisplayId{2};
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700567 const uint8_t hdmi1 = 0;
568 const uint8_t hdmi2 = 1;
569 const uint8_t hdmi3 = 2;
570
571 mFakePolicy->clearViewports();
572 // Add a viewport that's associated with some display port that's not of interest.
Michael Wrighta9cf4192022-12-01 23:46:39 +0000573 mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000574 /*isActive=*/true, uniqueId1, hdmi3, type);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700575 // Add another viewport, connected to HDMI1 port
Michael Wrighta9cf4192022-12-01 23:46:39 +0000576 mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000577 /*isActive=*/true, uniqueId2, hdmi1, type);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700578
579 // Check that correct display viewport was returned by comparing the display ports.
580 std::optional<DisplayViewport> hdmi1Viewport = mFakePolicy->getDisplayViewportByPort(hdmi1);
581 ASSERT_TRUE(hdmi1Viewport);
582 ASSERT_EQ(displayId2, hdmi1Viewport->displayId);
583 ASSERT_EQ(uniqueId2, hdmi1Viewport->uniqueId);
584
585 // Check that we can still get the same viewport using the uniqueId
586 hdmi1Viewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId2);
587 ASSERT_TRUE(hdmi1Viewport);
588 ASSERT_EQ(displayId2, hdmi1Viewport->displayId);
589 ASSERT_EQ(uniqueId2, hdmi1Viewport->uniqueId);
590 ASSERT_EQ(type, hdmi1Viewport->type);
591
592 // Check that we cannot find a port with "HDMI2", because we never added one
593 std::optional<DisplayViewport> hdmi2Viewport = mFakePolicy->getDisplayViewportByPort(hdmi2);
594 ASSERT_FALSE(hdmi2Viewport);
595}
596
Michael Wrightd02c5b62014-02-10 15:10:22 -0800597// --- InputReaderTest ---
598
599class InputReaderTest : public testing::Test {
600protected:
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700601 std::unique_ptr<TestInputListener> mFakeListener;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800602 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou3bc7e092019-07-24 17:43:30 -0700603 std::shared_ptr<FakeEventHub> mFakeEventHub;
Prabir Pradhan28efc192019-11-05 01:10:04 +0000604 std::unique_ptr<InstrumentedInputReader> mReader;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800605
Chris Yea52ade12020-08-27 16:49:20 -0700606 void SetUp() override {
Siarhei Vishniakou3bc7e092019-07-24 17:43:30 -0700607 mFakeEventHub = std::make_unique<FakeEventHub>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700608 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700609 mFakeListener = std::make_unique<TestInputListener>();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800610
Prabir Pradhan28efc192019-11-05 01:10:04 +0000611 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700612 *mFakeListener);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800613 }
614
Chris Yea52ade12020-08-27 16:49:20 -0700615 void TearDown() override {
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700616 mFakeListener.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800617 mFakePolicy.clear();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800618 }
619
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700620 void addDevice(int32_t eventHubId, const std::string& name,
621 ftl::Flags<InputDeviceClass> classes, const PropertyMap* configuration) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800622 mFakeEventHub->addDevice(eventHubId, name, classes);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800623
624 if (configuration) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800625 mFakeEventHub->addConfigurationMap(eventHubId, configuration);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800626 }
Liana Kazanovac3cf1a22024-07-18 17:18:21 +0000627 mFakeEventHub->finishDeviceScan();
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000628 mReader->loopOnce();
629 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700630 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Prabir Pradhane3da4bb2023-04-05 23:51:23 +0000631 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyInputDevicesChangedWasCalled());
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700632 ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800633 }
634
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800635 void disableDevice(int32_t deviceId) {
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700636 mFakePolicy->addDisabledDevice(deviceId);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000637 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::ENABLED_STATE);
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700638 }
639
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800640 void enableDevice(int32_t deviceId) {
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700641 mFakePolicy->removeDisabledDevice(deviceId);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000642 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::ENABLED_STATE);
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700643 }
644
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800645 FakeInputMapper& addDeviceWithFakeInputMapper(int32_t deviceId, int32_t eventHubId,
Chris Ye1b0c7342020-07-28 21:57:03 -0700646 const std::string& name,
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700647 ftl::Flags<InputDeviceClass> classes,
648 uint32_t sources,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800649 const PropertyMap* configuration) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800650 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, name);
Arpit Singh8e6fb252023-04-06 11:49:17 +0000651 FakeInputMapper& mapper =
652 device->addMapper<FakeInputMapper>(eventHubId,
653 mFakePolicy->getReaderConfiguration(), sources);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -0800654 mReader->pushNextDevice(device);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800655 addDevice(eventHubId, name, classes, configuration);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800656 return mapper;
657 }
658};
659
Chris Ye98d3f532020-10-01 21:48:59 -0700660TEST_F(InputReaderTest, PolicyGetInputDevices) {
661 ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard", InputDeviceClass::KEYBOARD, nullptr));
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700662 ASSERT_NO_FATAL_FAILURE(addDevice(2, "ignored", ftl::Flags<InputDeviceClass>(0),
Chris Ye98d3f532020-10-01 21:48:59 -0700663 nullptr)); // no classes so device will be ignored
Michael Wrightd02c5b62014-02-10 15:10:22 -0800664
665 // Should also have received a notification describing the new input devices.
Chris Ye98d3f532020-10-01 21:48:59 -0700666 const std::vector<InputDeviceInfo>& inputDevices = mFakePolicy->getInputDevices();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800667 ASSERT_EQ(1U, inputDevices.size());
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800668 ASSERT_EQ(END_RESERVED_ID + 1, inputDevices[0].getId());
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100669 ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800670 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, inputDevices[0].getKeyboardType());
671 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, inputDevices[0].getSources());
Siarhei Vishniakou1983a712021-06-04 19:27:09 +0000672 ASSERT_EQ(0U, inputDevices[0].getMotionRanges().size());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800673}
674
Vaibhav Devmurari5fc7d852023-03-17 18:43:33 +0000675TEST_F(InputReaderTest, InputDeviceRecreatedOnSysfsNodeChanged) {
676 ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard", InputDeviceClass::KEYBOARD, nullptr));
677 mFakeEventHub->setSysfsRootPath(1, "xyz");
678
679 // Should also have received a notification describing the new input device.
680 ASSERT_EQ(1U, mFakePolicy->getInputDevices().size());
681 InputDeviceInfo inputDevice = mFakePolicy->getInputDevices()[0];
682 ASSERT_EQ(0U, inputDevice.getLights().size());
683
684 RawLightInfo infoMonolight = {.id = 123,
685 .name = "mono_keyboard_backlight",
686 .maxBrightness = 255,
687 .flags = InputLightClass::BRIGHTNESS,
688 .path = ""};
689 mFakeEventHub->addRawLightInfo(/*rawId=*/123, std::move(infoMonolight));
690 mReader->sysfsNodeChanged("xyz");
691 mReader->loopOnce();
692
693 // Should also have received a notification describing the new recreated input device.
694 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
695 inputDevice = mFakePolicy->getInputDevices()[0];
696 ASSERT_EQ(1U, inputDevice.getLights().size());
697}
698
Chris Yee7310032020-09-22 15:36:28 -0700699TEST_F(InputReaderTest, GetMergedInputDevices) {
700 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
701 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
702 // Add two subdevices to device
703 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
704 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000705 device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
706 AINPUT_SOURCE_KEYBOARD);
707 device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
708 AINPUT_SOURCE_KEYBOARD);
Chris Yee7310032020-09-22 15:36:28 -0700709
710 // Push same device instance for next device to be added, so they'll have same identifier.
711 mReader->pushNextDevice(device);
712 mReader->pushNextDevice(device);
713 ASSERT_NO_FATAL_FAILURE(
714 addDevice(eventHubIds[0], "fake1", InputDeviceClass::KEYBOARD, nullptr));
715 ASSERT_NO_FATAL_FAILURE(
716 addDevice(eventHubIds[1], "fake2", InputDeviceClass::KEYBOARD, nullptr));
717
718 // Two devices will be merged to one input device as they have same identifier
Siarhei Vishniakou1983a712021-06-04 19:27:09 +0000719 ASSERT_EQ(1U, mFakePolicy->getInputDevices().size());
Chris Yee7310032020-09-22 15:36:28 -0700720}
721
Chris Yee14523a2020-12-19 13:46:00 -0800722TEST_F(InputReaderTest, GetMergedInputDevicesEnabled) {
723 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
724 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
725 // Add two subdevices to device
726 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
727 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000728 device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
729 AINPUT_SOURCE_KEYBOARD);
730 device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
731 AINPUT_SOURCE_KEYBOARD);
Chris Yee14523a2020-12-19 13:46:00 -0800732
733 // Push same device instance for next device to be added, so they'll have same identifier.
734 mReader->pushNextDevice(device);
735 mReader->pushNextDevice(device);
736 // Sensor device is initially disabled
737 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1",
738 InputDeviceClass::KEYBOARD | InputDeviceClass::SENSOR,
739 nullptr));
740 // Device is disabled because the only sub device is a sensor device and disabled initially.
741 ASSERT_FALSE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
742 ASSERT_FALSE(device->isEnabled());
743 ASSERT_NO_FATAL_FAILURE(
744 addDevice(eventHubIds[1], "fake2", InputDeviceClass::KEYBOARD, nullptr));
745 // The merged device is enabled if any sub device is enabled
746 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
747 ASSERT_TRUE(device->isEnabled());
748}
749
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700750TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800751 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700752 constexpr ftl::Flags<InputDeviceClass> deviceClass(InputDeviceClass::KEYBOARD);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800753 constexpr int32_t eventHubId = 1;
754 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700755 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000756 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
757 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -0800758 mReader->pushNextDevice(device);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800759 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700760
Liana Kazanovac3cf1a22024-07-18 17:18:21 +0000761 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(nullptr));
762
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700763 NotifyDeviceResetArgs resetArgs;
764 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700765 ASSERT_EQ(deviceId, resetArgs.deviceId);
766
767 ASSERT_EQ(device->isEnabled(), true);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800768 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000769 mReader->loopOnce();
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700770
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700771 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700772 ASSERT_EQ(deviceId, resetArgs.deviceId);
773 ASSERT_EQ(device->isEnabled(), false);
774
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800775 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000776 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700777 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
Liana Kazanovac3cf1a22024-07-18 17:18:21 +0000778 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasNotCalled());
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700779 ASSERT_EQ(device->isEnabled(), false);
780
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800781 enableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000782 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700783 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700784 ASSERT_EQ(deviceId, resetArgs.deviceId);
785 ASSERT_EQ(device->isEnabled(), true);
786}
787
Michael Wrightd02c5b62014-02-10 15:10:22 -0800788TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800789 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700790 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800791 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800792 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800793 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800794 AINPUT_SOURCE_KEYBOARD, nullptr);
795 mapper.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800796
797 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(0,
798 AINPUT_SOURCE_ANY, AKEYCODE_A))
799 << "Should return unknown when the device id is >= 0 but unknown.";
800
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800801 ASSERT_EQ(AKEY_STATE_UNKNOWN,
802 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
803 << "Should return unknown when the device id is valid but the sources are not "
804 "supported by the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800805
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800806 ASSERT_EQ(AKEY_STATE_DOWN,
807 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
808 AKEYCODE_A))
809 << "Should return value provided by mapper when device id is valid and the device "
810 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800811
812 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(-1,
813 AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
814 << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
815
816 ASSERT_EQ(AKEY_STATE_DOWN, mReader->getKeyCodeState(-1,
817 AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
818 << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
819}
820
Philip Junker4af3b3d2021-12-14 10:36:55 +0100821TEST_F(InputReaderTest, GetKeyCodeForKeyLocation_ForwardsRequestsToMappers) {
822 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
823 constexpr int32_t eventHubId = 1;
824 FakeInputMapper& mapper = addDeviceWithFakeInputMapper(deviceId, eventHubId, "keyboard",
825 InputDeviceClass::KEYBOARD,
826 AINPUT_SOURCE_KEYBOARD, nullptr);
827 mapper.addKeyCodeMapping(AKEYCODE_Y, AKEYCODE_Z);
828
829 ASSERT_EQ(AKEYCODE_UNKNOWN, mReader->getKeyCodeForKeyLocation(0, AKEYCODE_Y))
830 << "Should return unknown when the device with the specified id is not found.";
831
832 ASSERT_EQ(AKEYCODE_Z, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_Y))
833 << "Should return correct mapping when device id is valid and mapping exists.";
834
835 ASSERT_EQ(AKEYCODE_A, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_A))
836 << "Should return the location key code when device id is valid and there's no "
837 "mapping.";
838}
839
840TEST_F(InputReaderTest, GetKeyCodeForKeyLocation_NoKeyboardMapper) {
841 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
842 constexpr int32_t eventHubId = 1;
843 FakeInputMapper& mapper = addDeviceWithFakeInputMapper(deviceId, eventHubId, "joystick",
844 InputDeviceClass::JOYSTICK,
845 AINPUT_SOURCE_GAMEPAD, nullptr);
846 mapper.addKeyCodeMapping(AKEYCODE_Y, AKEYCODE_Z);
847
848 ASSERT_EQ(AKEYCODE_UNKNOWN, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_Y))
849 << "Should return unknown when the device id is valid but there is no keyboard mapper";
850}
851
Michael Wrightd02c5b62014-02-10 15:10:22 -0800852TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800853 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700854 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800855 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800856 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800857 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800858 AINPUT_SOURCE_KEYBOARD, nullptr);
859 mapper.setScanCodeState(KEY_A, AKEY_STATE_DOWN);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800860
861 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(0,
862 AINPUT_SOURCE_ANY, KEY_A))
863 << "Should return unknown when the device id is >= 0 but unknown.";
864
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800865 ASSERT_EQ(AKEY_STATE_UNKNOWN,
866 mReader->getScanCodeState(deviceId, AINPUT_SOURCE_TRACKBALL, KEY_A))
867 << "Should return unknown when the device id is valid but the sources are not "
868 "supported by the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800869
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800870 ASSERT_EQ(AKEY_STATE_DOWN,
871 mReader->getScanCodeState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
872 KEY_A))
873 << "Should return value provided by mapper when device id is valid and the device "
874 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800875
876 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(-1,
877 AINPUT_SOURCE_TRACKBALL, KEY_A))
878 << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
879
880 ASSERT_EQ(AKEY_STATE_DOWN, mReader->getScanCodeState(-1,
881 AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, KEY_A))
882 << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
883}
884
885TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800886 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700887 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800888 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800889 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800890 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800891 AINPUT_SOURCE_KEYBOARD, nullptr);
892 mapper.setSwitchState(SW_LID, AKEY_STATE_DOWN);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800893
894 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(0,
895 AINPUT_SOURCE_ANY, SW_LID))
896 << "Should return unknown when the device id is >= 0 but unknown.";
897
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800898 ASSERT_EQ(AKEY_STATE_UNKNOWN,
899 mReader->getSwitchState(deviceId, AINPUT_SOURCE_TRACKBALL, SW_LID))
900 << "Should return unknown when the device id is valid but the sources are not "
901 "supported by the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800902
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800903 ASSERT_EQ(AKEY_STATE_DOWN,
904 mReader->getSwitchState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
905 SW_LID))
906 << "Should return value provided by mapper when device id is valid and the device "
907 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800908
909 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(-1,
910 AINPUT_SOURCE_TRACKBALL, SW_LID))
911 << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
912
913 ASSERT_EQ(AKEY_STATE_DOWN, mReader->getSwitchState(-1,
914 AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, SW_LID))
915 << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
916}
917
918TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800919 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700920 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800921 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800922 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800923 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800924 AINPUT_SOURCE_KEYBOARD, nullptr);
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100925
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800926 mapper.addSupportedKeyCode(AKEYCODE_A);
927 mapper.addSupportedKeyCode(AKEYCODE_B);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800928
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700929 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800930 uint8_t flags[4] = { 0, 0, 0, 1 };
931
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700932 ASSERT_FALSE(mReader->hasKeys(0, AINPUT_SOURCE_ANY, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800933 << "Should return false when device id is >= 0 but unknown.";
934 ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
935
936 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700937 ASSERT_FALSE(mReader->hasKeys(deviceId, AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800938 << "Should return false when device id is valid but the sources are not supported by "
939 "the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800940 ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
941
942 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700943 ASSERT_TRUE(mReader->hasKeys(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800944 keyCodes, flags))
945 << "Should return value provided by mapper when device id is valid and the device "
946 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800947 ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
948
949 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700950 ASSERT_FALSE(mReader->hasKeys(-1, AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
951 << "Should return false when the device id is < 0 but the sources are not supported by "
952 "any device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800953 ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
954
955 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700956 ASSERT_TRUE(
957 mReader->hasKeys(-1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
958 << "Should return value provided by mapper when device id is < 0 and one of the "
959 "devices supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800960 ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
961}
962
Liana Kazanovac3cf1a22024-07-18 17:18:21 +0000963TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChanged) {
964 constexpr int32_t eventHubId = 1;
965 addDevice(eventHubId, "ignored", InputDeviceClass::KEYBOARD, nullptr);
966
967 NotifyConfigurationChangedArgs args;
968
969 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(&args));
970 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
971 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
972}
973
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000974TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800975 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700976 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000977 constexpr nsecs_t when = 0;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800978 constexpr int32_t eventHubId = 1;
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000979 constexpr nsecs_t readTime = 2;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800980 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800981 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800982 AINPUT_SOURCE_KEYBOARD, nullptr);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800983
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000984 mFakeEventHub->enqueueEvent(when, readTime, eventHubId, EV_KEY, KEY_A, 1);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000985 mReader->loopOnce();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800986 ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty());
987
988 RawEvent event;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800989 ASSERT_NO_FATAL_FAILURE(mapper.assertProcessWasCalled(&event));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000990 ASSERT_EQ(when, event.when);
991 ASSERT_EQ(readTime, event.readTime);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800992 ASSERT_EQ(eventHubId, event.deviceId);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800993 ASSERT_EQ(EV_KEY, event.type);
994 ASSERT_EQ(KEY_A, event.code);
995 ASSERT_EQ(1, event.value);
996}
997
Garfield Tan1c7bc862020-01-28 13:24:04 -0800998TEST_F(InputReaderTest, DeviceReset_RandomId) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800999 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001000 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001001 constexpr int32_t eventHubId = 1;
1002 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
Prabir Pradhan42611e02018-11-27 14:04:02 -08001003 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +00001004 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
1005 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001006 mReader->pushNextDevice(device);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001007 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Prabir Pradhan42611e02018-11-27 14:04:02 -08001008
1009 NotifyDeviceResetArgs resetArgs;
1010 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001011 int32_t prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001012
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001013 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001014 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -07001015 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tan1c7bc862020-01-28 13:24:04 -08001016 ASSERT_NE(prevId, resetArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001017 prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001018
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001019 enableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001020 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -07001021 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tan1c7bc862020-01-28 13:24:04 -08001022 ASSERT_NE(prevId, resetArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001023 prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001024
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001025 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001026 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -07001027 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tan1c7bc862020-01-28 13:24:04 -08001028 ASSERT_NE(prevId, resetArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001029 prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001030}
1031
Garfield Tan1c7bc862020-01-28 13:24:04 -08001032TEST_F(InputReaderTest, DeviceReset_GenerateIdWithInputReaderSource) {
1033 constexpr int32_t deviceId = 1;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001034 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Garfield Tan1c7bc862020-01-28 13:24:04 -08001035 constexpr int32_t eventHubId = 1;
1036 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
1037 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +00001038 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
1039 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001040 mReader->pushNextDevice(device);
Garfield Tan1c7bc862020-01-28 13:24:04 -08001041 ASSERT_NO_FATAL_FAILURE(addDevice(deviceId, "fake", deviceClass, nullptr));
1042
1043 NotifyDeviceResetArgs resetArgs;
1044 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1045 ASSERT_EQ(IdGenerator::Source::INPUT_READER, IdGenerator::getSource(resetArgs.id));
1046}
1047
Arthur Hungc23540e2018-11-29 20:42:11 +08001048TEST_F(InputReaderTest, Device_CanDispatchToDisplay) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001049 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001050 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001051 constexpr int32_t eventHubId = 1;
Arthur Hungc23540e2018-11-29 20:42:11 +08001052 const char* DEVICE_LOCATION = "USB1";
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001053 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
1054 FakeInputMapper& mapper =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001055 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
1056 AINPUT_SOURCE_TOUCHSCREEN);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001057 mReader->pushNextDevice(device);
Arthur Hungc23540e2018-11-29 20:42:11 +08001058
1059 const uint8_t hdmi1 = 1;
1060
1061 // Associated touch screen with second display.
1062 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
1063
1064 // Add default and second display.
Prabir Pradhan28efc192019-11-05 01:10:04 +00001065 mFakePolicy->clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00001066 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00001067 /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL);
Arthur Hungc23540e2018-11-29 20:42:11 +08001068 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +00001069 ui::ROTATION_0, /*isActive=*/true, "local:1", hdmi1,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01001070 ViewportType::EXTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001071 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::DISPLAY_INFO);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001072 mReader->loopOnce();
Prabir Pradhan28efc192019-11-05 01:10:04 +00001073
1074 // Add the device, and make sure all of the callbacks are triggered.
1075 // The device is added after the input port associations are processed since
1076 // we do not yet support dynamic device-to-display associations.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001077 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Liana Kazanovac3cf1a22024-07-18 17:18:21 +00001078 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled());
Prabir Pradhan28efc192019-11-05 01:10:04 +00001079 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001080 ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
Arthur Hungc23540e2018-11-29 20:42:11 +08001081
Arthur Hung2c9a3342019-07-23 14:18:59 +08001082 // Device should only dispatch to the specified display.
Arthur Hungc23540e2018-11-29 20:42:11 +08001083 ASSERT_EQ(deviceId, device->getId());
1084 ASSERT_FALSE(mReader->canDispatchToDisplay(deviceId, DISPLAY_ID));
1085 ASSERT_TRUE(mReader->canDispatchToDisplay(deviceId, SECONDARY_DISPLAY_ID));
Arthur Hung2c9a3342019-07-23 14:18:59 +08001086
1087 // Can't dispatch event from a disabled device.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001088 disableDevice(deviceId);
Prabir Pradhan28efc192019-11-05 01:10:04 +00001089 mReader->loopOnce();
Arthur Hung2c9a3342019-07-23 14:18:59 +08001090 ASSERT_FALSE(mReader->canDispatchToDisplay(deviceId, SECONDARY_DISPLAY_ID));
Arthur Hungc23540e2018-11-29 20:42:11 +08001091}
1092
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001093TEST_F(InputReaderTest, WhenEnabledChanges_AllSubdevicesAreUpdated) {
1094 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001095 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001096 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
1097 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
1098 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +00001099 device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
1100 AINPUT_SOURCE_KEYBOARD);
1101 device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
1102 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001103 mReader->pushNextDevice(device);
1104 mReader->pushNextDevice(device);
1105 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1", deviceClass, nullptr));
1106 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[1], "fake2", deviceClass, nullptr));
1107
Liana Kazanovac3cf1a22024-07-18 17:18:21 +00001108 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(nullptr));
1109
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001110 NotifyDeviceResetArgs resetArgs;
1111 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1112 ASSERT_EQ(deviceId, resetArgs.deviceId);
1113 ASSERT_TRUE(device->isEnabled());
1114 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
1115 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
1116
1117 disableDevice(deviceId);
1118 mReader->loopOnce();
1119
1120 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1121 ASSERT_EQ(deviceId, resetArgs.deviceId);
1122 ASSERT_FALSE(device->isEnabled());
1123 ASSERT_FALSE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
1124 ASSERT_FALSE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
1125
1126 enableDevice(deviceId);
1127 mReader->loopOnce();
1128
1129 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1130 ASSERT_EQ(deviceId, resetArgs.deviceId);
1131 ASSERT_TRUE(device->isEnabled());
1132 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
1133 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
1134}
1135
1136TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToSubdeviceMappers) {
1137 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001138 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001139 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
1140 // Add two subdevices to device
1141 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
1142 FakeInputMapper& mapperDevice1 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001143 device->addMapper<FakeInputMapper>(eventHubIds[0],
1144 mFakePolicy->getReaderConfiguration(),
1145 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001146 FakeInputMapper& mapperDevice2 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001147 device->addMapper<FakeInputMapper>(eventHubIds[1],
1148 mFakePolicy->getReaderConfiguration(),
1149 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001150 mReader->pushNextDevice(device);
1151 mReader->pushNextDevice(device);
1152 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1", deviceClass, nullptr));
1153 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[1], "fake2", deviceClass, nullptr));
1154
1155 mapperDevice1.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
1156 mapperDevice2.setKeyCodeState(AKEYCODE_B, AKEY_STATE_DOWN);
1157
1158 ASSERT_EQ(AKEY_STATE_DOWN,
1159 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_A));
1160 ASSERT_EQ(AKEY_STATE_DOWN,
1161 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_B));
1162 ASSERT_EQ(AKEY_STATE_UNKNOWN,
1163 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_C));
1164}
1165
Prabir Pradhan7e186182020-11-10 13:56:45 -08001166TEST_F(InputReaderTest, ChangingPointerCaptureNotifiesInputListener) {
1167 NotifyPointerCaptureChangedArgs args;
1168
Hiroki Sato25040232024-02-22 17:21:22 +09001169 auto request = mFakePolicy->setPointerCapture(/*window=*/sp<BBinder>::make());
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001170 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE);
Prabir Pradhan7e186182020-11-10 13:56:45 -08001171 mReader->loopOnce();
1172 mFakeListener->assertNotifyCaptureWasCalled(&args);
Hiroki Sato25040232024-02-22 17:21:22 +09001173 ASSERT_TRUE(args.request.isEnable()) << "Pointer Capture should be enabled.";
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001174 ASSERT_EQ(args.request, request) << "Pointer Capture sequence number should match.";
Prabir Pradhan7e186182020-11-10 13:56:45 -08001175
Hiroki Sato25040232024-02-22 17:21:22 +09001176 mFakePolicy->setPointerCapture(/*window=*/nullptr);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001177 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE);
Prabir Pradhan7e186182020-11-10 13:56:45 -08001178 mReader->loopOnce();
1179 mFakeListener->assertNotifyCaptureWasCalled(&args);
Hiroki Sato25040232024-02-22 17:21:22 +09001180 ASSERT_FALSE(args.request.isEnable()) << "Pointer Capture should be disabled.";
Prabir Pradhan7e186182020-11-10 13:56:45 -08001181
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001182 // Verify that the Pointer Capture state is not updated when the configuration value
Prabir Pradhan7e186182020-11-10 13:56:45 -08001183 // does not change.
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001184 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE);
Prabir Pradhan7e186182020-11-10 13:56:45 -08001185 mReader->loopOnce();
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001186 mFakeListener->assertNotifyCaptureWasNotCalled();
Prabir Pradhan7e186182020-11-10 13:56:45 -08001187}
1188
Prabir Pradhan018faea2024-05-08 21:52:54 +00001189TEST_F(InputReaderTest, GetLastUsedInputDeviceId) {
1190 constexpr int32_t FIRST_DEVICE_ID = END_RESERVED_ID + 1000;
1191 constexpr int32_t SECOND_DEVICE_ID = FIRST_DEVICE_ID + 1;
1192 FakeInputMapper& firstMapper =
1193 addDeviceWithFakeInputMapper(FIRST_DEVICE_ID, FIRST_DEVICE_ID, "first",
1194 InputDeviceClass::KEYBOARD, AINPUT_SOURCE_KEYBOARD,
1195 /*configuration=*/nullptr);
1196 FakeInputMapper& secondMapper =
1197 addDeviceWithFakeInputMapper(SECOND_DEVICE_ID, SECOND_DEVICE_ID, "second",
1198 InputDeviceClass::TOUCH_MT, AINPUT_SOURCE_STYLUS,
1199 /*configuration=*/nullptr);
1200
1201 ASSERT_EQ(ReservedInputDeviceId::INVALID_INPUT_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1202
1203 // Start a new key gesture from the first device
1204 firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
1205 .deviceId(FIRST_DEVICE_ID)
1206 .build()});
1207 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
1208 mReader->loopOnce();
1209 ASSERT_EQ(firstMapper.getDeviceId(), mReader->getLastUsedInputDeviceId());
1210
1211 // Start a new touch gesture from the second device
1212 secondMapper.setProcessResult(
1213 {MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
1214 .deviceId(SECOND_DEVICE_ID)
1215 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER))
1216 .build()});
1217 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
1218 mReader->loopOnce();
1219 ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1220
1221 // Releasing the key is not a new gesture, so it does not update the last used device
1222 firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
1223 .deviceId(FIRST_DEVICE_ID)
1224 .build()});
1225 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
1226 mReader->loopOnce();
1227 ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1228
1229 // But pressing a new key does start a new gesture
1230 firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
1231 .deviceId(FIRST_DEVICE_ID)
1232 .build()});
1233 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
1234 mReader->loopOnce();
1235 ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1236
1237 // Moving or ending a touch gesture does not update the last used device
1238 secondMapper.setProcessResult(
1239 {MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
1240 .deviceId(SECOND_DEVICE_ID)
1241 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
1242 .build()});
1243 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
1244 mReader->loopOnce();
1245 ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1246 secondMapper.setProcessResult({MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
1247 .deviceId(SECOND_DEVICE_ID)
1248 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
1249 .build()});
1250 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
1251 mReader->loopOnce();
1252 ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1253
1254 // Starting a new hover gesture updates the last used device
1255 secondMapper.setProcessResult(
1256 {MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1257 .deviceId(SECOND_DEVICE_ID)
1258 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
1259 .build()});
1260 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
1261 mReader->loopOnce();
1262 ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1263}
1264
Chris Ye87143712020-11-10 05:05:58 +00001265class FakeVibratorInputMapper : public FakeInputMapper {
1266public:
Arpit Singh8e6fb252023-04-06 11:49:17 +00001267 FakeVibratorInputMapper(InputDeviceContext& deviceContext,
1268 const InputReaderConfiguration& readerConfig, uint32_t sources)
1269 : FakeInputMapper(deviceContext, readerConfig, sources) {}
Chris Ye87143712020-11-10 05:05:58 +00001270
1271 std::vector<int32_t> getVibratorIds() override { return getDeviceContext().getVibratorIds(); }
1272};
1273
1274TEST_F(InputReaderTest, VibratorGetVibratorIds) {
1275 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001276 ftl::Flags<InputDeviceClass> deviceClass =
1277 InputDeviceClass::KEYBOARD | InputDeviceClass::VIBRATOR;
Chris Ye87143712020-11-10 05:05:58 +00001278 constexpr int32_t eventHubId = 1;
1279 const char* DEVICE_LOCATION = "BLUETOOTH";
1280 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
1281 FakeVibratorInputMapper& mapper =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001282 device->addMapper<FakeVibratorInputMapper>(eventHubId,
1283 mFakePolicy->getReaderConfiguration(),
1284 AINPUT_SOURCE_KEYBOARD);
Chris Ye87143712020-11-10 05:05:58 +00001285 mReader->pushNextDevice(device);
1286
1287 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1288 ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
1289
1290 ASSERT_EQ(mapper.getVibratorIds().size(), 2U);
1291 ASSERT_EQ(mReader->getVibratorIds(deviceId).size(), 2U);
1292}
1293
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001294// --- FakePeripheralController ---
Kim Low03ea0352020-11-06 12:45:07 -08001295
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001296class FakePeripheralController : public PeripheralControllerInterface {
Chris Yee2b1e5c2021-03-10 22:45:12 -08001297public:
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001298 FakePeripheralController(InputDeviceContext& deviceContext) : mDeviceContext(deviceContext) {}
Chris Yee2b1e5c2021-03-10 22:45:12 -08001299
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001300 ~FakePeripheralController() override {}
Chris Yee2b1e5c2021-03-10 22:45:12 -08001301
Andy Chenf9f1a022022-08-29 20:07:10 -04001302 int32_t getEventHubId() const { return getDeviceContext().getEventHubId(); }
1303
Chris Yee2b1e5c2021-03-10 22:45:12 -08001304 void populateDeviceInfo(InputDeviceInfo* deviceInfo) override {}
1305
1306 void dump(std::string& dump) override {}
1307
1308 std::optional<int32_t> getBatteryCapacity(int32_t batteryId) override {
1309 return getDeviceContext().getBatteryCapacity(batteryId);
Kim Low03ea0352020-11-06 12:45:07 -08001310 }
1311
Chris Yee2b1e5c2021-03-10 22:45:12 -08001312 std::optional<int32_t> getBatteryStatus(int32_t batteryId) override {
1313 return getDeviceContext().getBatteryStatus(batteryId);
Kim Low03ea0352020-11-06 12:45:07 -08001314 }
Chris Ye3fdbfef2021-01-06 18:45:18 -08001315
1316 bool setLightColor(int32_t lightId, int32_t color) override {
1317 getDeviceContext().setLightBrightness(lightId, color >> 24);
1318 return true;
1319 }
1320
1321 std::optional<int32_t> getLightColor(int32_t lightId) override {
1322 std::optional<int32_t> result = getDeviceContext().getLightBrightness(lightId);
1323 if (!result.has_value()) {
1324 return std::nullopt;
1325 }
1326 return result.value() << 24;
1327 }
Chris Yee2b1e5c2021-03-10 22:45:12 -08001328
1329 bool setLightPlayerId(int32_t lightId, int32_t playerId) override { return true; }
1330
1331 std::optional<int32_t> getLightPlayerId(int32_t lightId) override { return std::nullopt; }
1332
1333private:
1334 InputDeviceContext& mDeviceContext;
1335 inline int32_t getDeviceId() { return mDeviceContext.getId(); }
1336 inline InputDeviceContext& getDeviceContext() { return mDeviceContext; }
Andy Chenf9f1a022022-08-29 20:07:10 -04001337 inline InputDeviceContext& getDeviceContext() const { return mDeviceContext; }
Chris Ye3fdbfef2021-01-06 18:45:18 -08001338};
1339
Chris Yee2b1e5c2021-03-10 22:45:12 -08001340TEST_F(InputReaderTest, BatteryGetCapacity) {
1341 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001342 ftl::Flags<InputDeviceClass> deviceClass =
1343 InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
Chris Yee2b1e5c2021-03-10 22:45:12 -08001344 constexpr int32_t eventHubId = 1;
1345 const char* DEVICE_LOCATION = "BLUETOOTH";
1346 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001347 FakePeripheralController& controller =
1348 device->addController<FakePeripheralController>(eventHubId);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001349 mReader->pushNextDevice(device);
1350
1351 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1352
Harry Cuttsa5b71292022-11-28 12:56:17 +00001353 ASSERT_EQ(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY),
1354 FakeEventHub::BATTERY_CAPACITY);
1355 ASSERT_EQ(mReader->getBatteryCapacity(deviceId), FakeEventHub::BATTERY_CAPACITY);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001356}
1357
1358TEST_F(InputReaderTest, BatteryGetStatus) {
1359 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001360 ftl::Flags<InputDeviceClass> deviceClass =
1361 InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
Chris Yee2b1e5c2021-03-10 22:45:12 -08001362 constexpr int32_t eventHubId = 1;
1363 const char* DEVICE_LOCATION = "BLUETOOTH";
1364 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001365 FakePeripheralController& controller =
1366 device->addController<FakePeripheralController>(eventHubId);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001367 mReader->pushNextDevice(device);
1368
1369 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1370
Harry Cuttsa5b71292022-11-28 12:56:17 +00001371 ASSERT_EQ(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY),
1372 FakeEventHub::BATTERY_STATUS);
1373 ASSERT_EQ(mReader->getBatteryStatus(deviceId), FakeEventHub::BATTERY_STATUS);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001374}
1375
Prabir Pradhane287ecd2022-09-07 21:18:05 +00001376TEST_F(InputReaderTest, BatteryGetDevicePath) {
1377 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
1378 ftl::Flags<InputDeviceClass> deviceClass =
1379 InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
1380 constexpr int32_t eventHubId = 1;
1381 const char* DEVICE_LOCATION = "BLUETOOTH";
1382 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
1383 device->addController<FakePeripheralController>(eventHubId);
1384 mReader->pushNextDevice(device);
1385
1386 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1387
Harry Cuttsa5b71292022-11-28 12:56:17 +00001388 ASSERT_EQ(mReader->getBatteryDevicePath(deviceId), FakeEventHub::BATTERY_DEVPATH);
Prabir Pradhane287ecd2022-09-07 21:18:05 +00001389}
1390
Chris Ye3fdbfef2021-01-06 18:45:18 -08001391TEST_F(InputReaderTest, LightGetColor) {
1392 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001393 ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::LIGHT;
Chris Ye3fdbfef2021-01-06 18:45:18 -08001394 constexpr int32_t eventHubId = 1;
1395 const char* DEVICE_LOCATION = "BLUETOOTH";
1396 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001397 FakePeripheralController& controller =
1398 device->addController<FakePeripheralController>(eventHubId);
Chris Ye3fdbfef2021-01-06 18:45:18 -08001399 mReader->pushNextDevice(device);
1400 RawLightInfo info = {.id = 1,
1401 .name = "Mono",
1402 .maxBrightness = 255,
1403 .flags = InputLightClass::BRIGHTNESS,
1404 .path = ""};
Harry Cutts33476232023-01-30 19:57:29 +00001405 mFakeEventHub->addRawLightInfo(/*rawId=*/1, std::move(info));
1406 mFakeEventHub->fakeLightBrightness(/*rawId=*/1, 0x55);
Chris Ye3fdbfef2021-01-06 18:45:18 -08001407
1408 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Chris Ye3fdbfef2021-01-06 18:45:18 -08001409
Harry Cutts33476232023-01-30 19:57:29 +00001410 ASSERT_TRUE(controller.setLightColor(/*lightId=*/1, LIGHT_BRIGHTNESS));
1411 ASSERT_EQ(controller.getLightColor(/*lightId=*/1), LIGHT_BRIGHTNESS);
1412 ASSERT_TRUE(mReader->setLightColor(deviceId, /*lightId=*/1, LIGHT_BRIGHTNESS));
1413 ASSERT_EQ(mReader->getLightColor(deviceId, /*lightId=*/1), LIGHT_BRIGHTNESS);
Chris Ye3fdbfef2021-01-06 18:45:18 -08001414}
1415
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001416// --- InputReaderIntegrationTest ---
1417
1418// These tests create and interact with the InputReader only through its interface.
1419// The InputReader is started during SetUp(), which starts its processing in its own
1420// thread. The tests use linux uinput to emulate input devices.
1421// NOTE: Interacting with the physical device while these tests are running may cause
1422// the tests to fail.
1423class InputReaderIntegrationTest : public testing::Test {
1424protected:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001425 std::unique_ptr<TestInputListener> mTestListener;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001426 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001427 std::unique_ptr<InputReaderInterface> mReader;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001428
Prabir Pradhanafb7d612024-01-08 22:45:24 +00001429 constexpr static auto EVENT_HAPPENED_TIMEOUT = 2000ms;
1430 constexpr static auto EVENT_DID_NOT_HAPPEN_TIMEOUT = 30ms;
1431
Chris Yea52ade12020-08-27 16:49:20 -07001432 void SetUp() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001433#if !defined(__ANDROID__)
1434 GTEST_SKIP();
1435#endif
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001436 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001437
Arpit Singh440bf652023-08-09 09:23:43 +00001438 setupInputReader();
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001439 }
1440
Chris Yea52ade12020-08-27 16:49:20 -07001441 void TearDown() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001442#if !defined(__ANDROID__)
1443 return;
1444#endif
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001445 ASSERT_EQ(mReader->stop(), OK);
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001446 mReader.reset();
1447 mTestListener.reset();
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001448 mFakePolicy.clear();
1449 }
Prabir Pradhanda20b172022-09-26 17:01:18 +00001450
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001451 std::optional<InputDeviceInfo> waitForDevice(const std::string& deviceName) {
1452 std::chrono::time_point start = std::chrono::steady_clock::now();
1453 while (true) {
1454 const std::vector<InputDeviceInfo> inputDevices = mFakePolicy->getInputDevices();
1455 const auto& it = std::find_if(inputDevices.begin(), inputDevices.end(),
1456 [&deviceName](const InputDeviceInfo& info) {
1457 return info.getIdentifier().name == deviceName;
1458 });
1459 if (it != inputDevices.end()) {
1460 return std::make_optional(*it);
1461 }
1462 std::this_thread::sleep_for(1ms);
1463 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
1464 if (elapsed > 5s) {
1465 return {};
1466 }
1467 }
Prabir Pradhanda20b172022-09-26 17:01:18 +00001468 }
Arpit Singh440bf652023-08-09 09:23:43 +00001469
1470 void setupInputReader() {
Prabir Pradhanafb7d612024-01-08 22:45:24 +00001471 mTestListener = std::make_unique<TestInputListener>(EVENT_HAPPENED_TIMEOUT,
1472 EVENT_DID_NOT_HAPPEN_TIMEOUT);
Arpit Singh440bf652023-08-09 09:23:43 +00001473
1474 mReader = std::make_unique<InputReader>(std::make_shared<EventHub>(), mFakePolicy,
1475 *mTestListener);
1476 ASSERT_EQ(mReader->start(), OK);
1477
1478 // Since this test is run on a real device, all the input devices connected
1479 // to the test device will show up in mReader. We wait for those input devices to
1480 // show up before beginning the tests.
Arpit Singh440bf652023-08-09 09:23:43 +00001481 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyInputDevicesChangedWasCalled());
Liana Kazanovac3cf1a22024-07-18 17:18:21 +00001482 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Vaibhav Devmuraric109d812024-07-10 14:21:27 +00001483 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Liana Kazanovac3cf1a22024-07-18 17:18:21 +00001484 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Arpit Singh440bf652023-08-09 09:23:43 +00001485 }
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001486};
1487
1488TEST_F(InputReaderIntegrationTest, TestInvalidDevice) {
1489 // An invalid input device that is only used for this test.
1490 class InvalidUinputDevice : public UinputDevice {
1491 public:
Harry Cutts33476232023-01-30 19:57:29 +00001492 InvalidUinputDevice() : UinputDevice("Invalid Device", /*productId=*/99) {}
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001493
1494 private:
1495 void configureDevice(int fd, uinput_user_dev* device) override {}
1496 };
1497
1498 const size_t numDevices = mFakePolicy->getInputDevices().size();
1499
1500 // UinputDevice does not set any event or key bits, so InputReader should not
1501 // consider it as a valid device.
1502 std::unique_ptr<UinputDevice> invalidDevice = createUinputDevice<InvalidUinputDevice>();
1503 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesNotChanged());
Liana Kazanovac3cf1a22024-07-18 17:18:21 +00001504 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationNotChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001505 ASSERT_EQ(numDevices, mFakePolicy->getInputDevices().size());
1506
1507 invalidDevice.reset();
1508 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesNotChanged());
Liana Kazanovac3cf1a22024-07-18 17:18:21 +00001509 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationNotChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001510 ASSERT_EQ(numDevices, mFakePolicy->getInputDevices().size());
1511}
1512
1513TEST_F(InputReaderIntegrationTest, AddNewDevice) {
1514 const size_t initialNumDevices = mFakePolicy->getInputDevices().size();
1515
1516 std::unique_ptr<UinputHomeKey> keyboard = createUinputDevice<UinputHomeKey>();
1517 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Liana Kazanovac3cf1a22024-07-18 17:18:21 +00001518 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001519 ASSERT_EQ(initialNumDevices + 1, mFakePolicy->getInputDevices().size());
1520
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001521 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001522 ASSERT_TRUE(device.has_value());
1523 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, device->getKeyboardType());
1524 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources());
1525 ASSERT_EQ(0U, device->getMotionRanges().size());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001526
1527 keyboard.reset();
1528 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Liana Kazanovac3cf1a22024-07-18 17:18:21 +00001529 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001530 ASSERT_EQ(initialNumDevices, mFakePolicy->getInputDevices().size());
1531}
1532
1533TEST_F(InputReaderIntegrationTest, SendsEventsToInputListener) {
1534 std::unique_ptr<UinputHomeKey> keyboard = createUinputDevice<UinputHomeKey>();
1535 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1536
Liana Kazanovac3cf1a22024-07-18 17:18:21 +00001537 NotifyConfigurationChangedArgs configChangedArgs;
1538 ASSERT_NO_FATAL_FAILURE(
1539 mTestListener->assertNotifyConfigurationChangedWasCalled(&configChangedArgs));
1540 int32_t prevId = configChangedArgs.id;
1541 nsecs_t prevTimestamp = configChangedArgs.eventTime;
1542
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001543 NotifyKeyArgs keyArgs;
1544 keyboard->pressAndReleaseHomeKey();
1545 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs));
1546 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
Liana Kazanovac3cf1a22024-07-18 17:18:21 +00001547 ASSERT_NE(prevId, keyArgs.id);
1548 prevId = keyArgs.id;
1549 ASSERT_LE(prevTimestamp, keyArgs.eventTime);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001550 ASSERT_LE(keyArgs.eventTime, keyArgs.readTime);
Liana Kazanovac3cf1a22024-07-18 17:18:21 +00001551 prevTimestamp = keyArgs.eventTime;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001552
1553 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs));
1554 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
Garfield Tan1c7bc862020-01-28 13:24:04 -08001555 ASSERT_NE(prevId, keyArgs.id);
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001556 ASSERT_LE(prevTimestamp, keyArgs.eventTime);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001557 ASSERT_LE(keyArgs.eventTime, keyArgs.readTime);
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001558}
Michael Wrightd02c5b62014-02-10 15:10:22 -08001559
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001560TEST_F(InputReaderIntegrationTest, ExternalStylusesButtons) {
1561 std::unique_ptr<UinputExternalStylus> stylus = createUinputDevice<UinputExternalStylus>();
1562 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1563
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001564 const auto device = waitForDevice(stylus->getName());
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001565 ASSERT_TRUE(device.has_value());
1566
Prabir Pradhana3621852022-10-14 18:57:23 +00001567 // An external stylus with buttons should also be recognized as a keyboard.
1568 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_STYLUS, device->getSources())
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001569 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1570 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, device->getKeyboardType());
1571
1572 const auto DOWN =
1573 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD));
1574 const auto UP = AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD));
1575
1576 stylus->pressAndReleaseKey(BTN_STYLUS);
1577 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1578 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
1579 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1580 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
1581
1582 stylus->pressAndReleaseKey(BTN_STYLUS2);
1583 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1584 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_SECONDARY))));
1585 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1586 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_SECONDARY))));
1587
1588 stylus->pressAndReleaseKey(BTN_STYLUS3);
1589 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1590 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_TERTIARY))));
1591 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1592 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_TERTIARY))));
1593}
1594
Prabir Pradhan3c28b942023-08-18 20:02:01 +00001595TEST_F(InputReaderIntegrationTest, KeyboardWithStylusButtons) {
1596 std::unique_ptr<UinputKeyboard> keyboard =
1597 createUinputDevice<UinputKeyboard>("KeyboardWithStylusButtons", /*productId=*/99,
1598 std::initializer_list<int>{KEY_Q, KEY_W, KEY_E,
1599 KEY_R, KEY_T, KEY_Y,
1600 BTN_STYLUS, BTN_STYLUS2,
1601 BTN_STYLUS3});
1602 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1603
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001604 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhan3c28b942023-08-18 20:02:01 +00001605 ASSERT_TRUE(device.has_value());
1606
1607 // An alphabetical keyboard that reports stylus buttons should not be recognized as a stylus.
1608 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources())
1609 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1610 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, device->getKeyboardType());
1611}
1612
Prabir Pradhan37a819b2023-08-22 23:20:16 +00001613TEST_F(InputReaderIntegrationTest, HidUsageKeyboardIsNotAStylus) {
1614 // Create a Uinput keyboard that simulates a keyboard that can report HID usage codes. The
1615 // hid-input driver reports HID usage codes using the value for EV_MSC MSC_SCAN event.
1616 std::unique_ptr<UinputKeyboardWithHidUsage> keyboard =
1617 createUinputDevice<UinputKeyboardWithHidUsage>(
1618 std::initializer_list<int>{KEY_VOLUMEUP, KEY_VOLUMEDOWN});
1619 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1620
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001621 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhan37a819b2023-08-22 23:20:16 +00001622 ASSERT_TRUE(device.has_value());
1623
1624 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources())
1625 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1626
1627 // If a device supports reporting HID usage codes, it shouldn't automatically support
1628 // stylus keys.
1629 const std::vector<int> keycodes{AKEYCODE_STYLUS_BUTTON_PRIMARY};
1630 uint8_t outFlags[] = {0};
1631 ASSERT_TRUE(mReader->hasKeys(device->getId(), AINPUT_SOURCE_KEYBOARD, keycodes, outFlags));
1632 ASSERT_EQ(0, outFlags[0]) << "Keyboard should not have stylus button";
1633}
1634
Siarhei Vishniakoua0d2b802020-05-13 14:00:31 -07001635/**
1636 * The Steam controller sends BTN_GEAR_DOWN and BTN_GEAR_UP for the two "paddle" buttons
1637 * on the back. In this test, we make sure that BTN_GEAR_DOWN / BTN_WHEEL and BTN_GEAR_UP
1638 * are passed to the listener.
1639 */
1640static_assert(BTN_GEAR_DOWN == BTN_WHEEL);
1641TEST_F(InputReaderIntegrationTest, SendsGearDownAndUpToInputListener) {
1642 std::unique_ptr<UinputSteamController> controller = createUinputDevice<UinputSteamController>();
1643 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1644 NotifyKeyArgs keyArgs;
1645
1646 controller->pressAndReleaseKey(BTN_GEAR_DOWN);
1647 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_DOWN
1648 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_UP
1649 ASSERT_EQ(BTN_GEAR_DOWN, keyArgs.scanCode);
1650
1651 controller->pressAndReleaseKey(BTN_GEAR_UP);
1652 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_DOWN
1653 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_UP
1654 ASSERT_EQ(BTN_GEAR_UP, keyArgs.scanCode);
1655}
1656
Prabir Pradhan484d55a2022-10-14 23:17:16 +00001657// --- TouchIntegrationTest ---
1658
Arpit Singh440bf652023-08-09 09:23:43 +00001659class BaseTouchIntegrationTest : public InputReaderIntegrationTest {
Arthur Hungaab25622020-01-16 11:22:11 +08001660protected:
Arthur Hungaab25622020-01-16 11:22:11 +08001661 const std::string UNIQUE_ID = "local:0";
1662
Chris Yea52ade12020-08-27 16:49:20 -07001663 void SetUp() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001664#if !defined(__ANDROID__)
1665 GTEST_SKIP();
1666#endif
Arthur Hungaab25622020-01-16 11:22:11 +08001667 InputReaderIntegrationTest::SetUp();
1668 // At least add an internal display.
Michael Wrighta9cf4192022-12-01 23:46:39 +00001669 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
1670 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Arthur Hungaab25622020-01-16 11:22:11 +08001671
1672 mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT));
1673 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Liana Kazanovac3cf1a22024-07-18 17:18:21 +00001674 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
1675 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001676 const auto info = waitForDevice(mDevice->getName());
Prabir Pradhanda20b172022-09-26 17:01:18 +00001677 ASSERT_TRUE(info);
1678 mDeviceInfo = *info;
Arthur Hungaab25622020-01-16 11:22:11 +08001679 }
1680
Linnan Li13bf76a2024-05-05 19:18:02 +08001681 void setDisplayInfoAndReconfigure(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
Michael Wrighta9cf4192022-12-01 23:46:39 +00001682 ui::Rotation orientation, const std::string& uniqueId,
Arthur Hungaab25622020-01-16 11:22:11 +08001683 std::optional<uint8_t> physicalPort,
1684 ViewportType viewportType) {
Harry Cutts33476232023-01-30 19:57:29 +00001685 mFakePolicy->addDisplayViewport(displayId, width, height, orientation, /*isActive=*/true,
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00001686 uniqueId, physicalPort, viewportType);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001687 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hungaab25622020-01-16 11:22:11 +08001688 }
1689
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001690 void assertReceivedMotion(int32_t action, const std::vector<Point>& points) {
1691 NotifyMotionArgs args;
1692 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1693 EXPECT_EQ(action, args.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07001694 ASSERT_EQ(points.size(), args.getPointerCount());
1695 for (size_t i = 0; i < args.getPointerCount(); i++) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001696 EXPECT_EQ(points[i].x, args.pointerCoords[i].getX());
1697 EXPECT_EQ(points[i].y, args.pointerCoords[i].getY());
1698 }
1699 }
1700
Arthur Hungaab25622020-01-16 11:22:11 +08001701 std::unique_ptr<UinputTouchScreen> mDevice;
Prabir Pradhanda20b172022-09-26 17:01:18 +00001702 InputDeviceInfo mDeviceInfo;
Arthur Hungaab25622020-01-16 11:22:11 +08001703};
1704
Arpit Singh440bf652023-08-09 09:23:43 +00001705enum class TouchIntegrationTestDisplays { DISPLAY_INTERNAL, DISPLAY_INPUT_PORT, DISPLAY_UNIQUE_ID };
1706
1707class TouchIntegrationTest : public BaseTouchIntegrationTest,
1708 public testing::WithParamInterface<TouchIntegrationTestDisplays> {
1709protected:
1710 static constexpr std::optional<uint8_t> DISPLAY_PORT = 0;
1711 const std::string INPUT_PORT = "uinput_touch/input0";
1712
1713 void SetUp() override {
1714#if !defined(__ANDROID__)
1715 GTEST_SKIP();
1716#endif
1717 if (GetParam() == TouchIntegrationTestDisplays::DISPLAY_INTERNAL) {
1718 BaseTouchIntegrationTest::SetUp();
1719 return;
1720 }
1721
1722 // setup policy with a input-port or UniqueId association to the display
1723 bool isInputPortAssociation =
1724 GetParam() == TouchIntegrationTestDisplays::DISPLAY_INPUT_PORT;
1725
1726 mFakePolicy = sp<FakeInputReaderPolicy>::make();
1727 if (isInputPortAssociation) {
1728 mFakePolicy->addInputPortAssociation(INPUT_PORT, DISPLAY_PORT.value());
1729 } else {
1730 mFakePolicy->addInputUniqueIdAssociation(INPUT_PORT, UNIQUE_ID);
1731 }
Arpit Singh440bf652023-08-09 09:23:43 +00001732
1733 InputReaderIntegrationTest::setupInputReader();
1734
1735 mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT),
1736 INPUT_PORT);
1737 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1738
1739 // Add a display linked to a physical port or UniqueId.
1740 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
1741 UNIQUE_ID, isInputPortAssociation ? DISPLAY_PORT : NO_PORT,
1742 ViewportType::INTERNAL);
1743 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Liana Kazanovac3cf1a22024-07-18 17:18:21 +00001744 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
1745 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001746 const auto info = waitForDevice(mDevice->getName());
Arpit Singh440bf652023-08-09 09:23:43 +00001747 ASSERT_TRUE(info);
1748 mDeviceInfo = *info;
1749 }
1750};
1751
1752TEST_P(TouchIntegrationTest, MultiTouchDeviceSource) {
Prabir Pradhanf9a41282022-10-25 17:15:50 +00001753 // The UinputTouchScreen is an MT device that supports MT_TOOL_TYPE and also supports stylus
1754 // buttons. It should show up as a touchscreen, stylus, and keyboard (for reporting button
1755 // presses).
1756 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD,
1757 mDeviceInfo.getSources());
1758}
1759
Arpit Singh440bf652023-08-09 09:23:43 +00001760TEST_P(TouchIntegrationTest, InputEvent_ProcessSingleTouch) {
Arthur Hungaab25622020-01-16 11:22:11 +08001761 NotifyMotionArgs args;
1762 const Point centerPoint = mDevice->getCenterPoint();
1763
1764 // ACTION_DOWN
Arthur Hung9ad18942021-06-19 02:04:46 +00001765 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001766 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001767 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001768 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1769 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1770
1771 // ACTION_MOVE
1772 mDevice->sendMove(centerPoint + Point(1, 1));
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001773 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001774 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1775 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1776
1777 // ACTION_UP
1778 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001779 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001780 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1781 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
1782}
1783
Arpit Singh440bf652023-08-09 09:23:43 +00001784TEST_P(TouchIntegrationTest, InputEvent_ProcessMultiTouch) {
Arthur Hungaab25622020-01-16 11:22:11 +08001785 NotifyMotionArgs args;
1786 const Point centerPoint = mDevice->getCenterPoint();
1787
1788 // ACTION_DOWN
Arthur Hung9ad18942021-06-19 02:04:46 +00001789 mDevice->sendSlot(FIRST_SLOT);
1790 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001791 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001792 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001793 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1794 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1795
1796 // ACTION_POINTER_DOWN (Second slot)
1797 const Point secondPoint = centerPoint + Point(100, 100);
1798 mDevice->sendSlot(SECOND_SLOT);
1799 mDevice->sendTrackingId(SECOND_TRACKING_ID);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001800 mDevice->sendDown(secondPoint);
1801 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001802 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001803 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001804
1805 // ACTION_MOVE (Second slot)
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001806 mDevice->sendMove(secondPoint + Point(1, 1));
1807 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001808 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1809 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1810
1811 // ACTION_POINTER_UP (Second slot)
arthurhungcc7f9802020-04-30 17:55:40 +08001812 mDevice->sendPointerUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001813 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001814 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001815 ASSERT_EQ(ACTION_POINTER_1_UP, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001816
1817 // ACTION_UP
1818 mDevice->sendSlot(FIRST_SLOT);
1819 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001820 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001821 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1822 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
1823}
1824
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001825/**
1826 * What happens when a pointer goes up while another pointer moves in the same frame? Are POINTER_UP
1827 * events guaranteed to contain the same data as a preceding MOVE, or can they contain different
1828 * data?
1829 * In this test, we try to send a change in coordinates in Pointer 0 in the same frame as the
1830 * liftoff of Pointer 1. We check that POINTER_UP event is generated first, and the MOVE event
1831 * for Pointer 0 only is generated after.
1832 * Suppose we are only interested in learning the movement of Pointer 0. If we only observe MOVE
1833 * events, we will not miss any information.
1834 * Even though the Pointer 1 up event contains updated Pointer 0 coordinates, there is another MOVE
1835 * event generated afterwards that contains the newest movement of pointer 0.
1836 * This is important for palm rejection. If there is a subsequent InputListener stage that detects
1837 * palms, and wants to cancel Pointer 1, then it is safe to simply drop POINTER_1_UP event without
1838 * losing information about non-palm pointers.
1839 */
Arpit Singh440bf652023-08-09 09:23:43 +00001840TEST_P(TouchIntegrationTest, MultiTouch_PointerMoveAndSecondPointerUp) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001841 NotifyMotionArgs args;
1842 const Point centerPoint = mDevice->getCenterPoint();
1843
1844 // ACTION_DOWN
1845 mDevice->sendSlot(FIRST_SLOT);
1846 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1847 mDevice->sendDown(centerPoint);
1848 mDevice->sendSync();
1849 assertReceivedMotion(AMOTION_EVENT_ACTION_DOWN, {centerPoint});
1850
1851 // ACTION_POINTER_DOWN (Second slot)
1852 const Point secondPoint = centerPoint + Point(100, 100);
1853 mDevice->sendSlot(SECOND_SLOT);
1854 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1855 mDevice->sendDown(secondPoint);
1856 mDevice->sendSync();
1857 assertReceivedMotion(ACTION_POINTER_1_DOWN, {centerPoint, secondPoint});
1858
1859 // ACTION_MOVE (First slot)
1860 mDevice->sendSlot(FIRST_SLOT);
1861 mDevice->sendMove(centerPoint + Point(5, 5));
1862 // ACTION_POINTER_UP (Second slot)
1863 mDevice->sendSlot(SECOND_SLOT);
1864 mDevice->sendPointerUp();
1865 // Send a single sync for the above 2 pointer updates
1866 mDevice->sendSync();
1867
1868 // First, we should get POINTER_UP for the second pointer
1869 assertReceivedMotion(ACTION_POINTER_1_UP,
1870 {/*first pointer */ centerPoint + Point(5, 5),
1871 /*second pointer*/ secondPoint});
1872
1873 // Next, the MOVE event for the first pointer
1874 assertReceivedMotion(AMOTION_EVENT_ACTION_MOVE, {centerPoint + Point(5, 5)});
1875}
1876
1877/**
1878 * Similar scenario as above. The difference is that when the second pointer goes up, it will first
1879 * move, and then it will go up, all in the same frame.
1880 * In this scenario, the movement of the second pointer just prior to liftoff is ignored, and never
1881 * gets sent to the listener.
1882 */
Arpit Singh440bf652023-08-09 09:23:43 +00001883TEST_P(TouchIntegrationTest, MultiTouch_PointerMoveAndSecondPointerMoveAndUp) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001884 NotifyMotionArgs args;
1885 const Point centerPoint = mDevice->getCenterPoint();
1886
1887 // ACTION_DOWN
1888 mDevice->sendSlot(FIRST_SLOT);
1889 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1890 mDevice->sendDown(centerPoint);
1891 mDevice->sendSync();
1892 assertReceivedMotion(AMOTION_EVENT_ACTION_DOWN, {centerPoint});
1893
1894 // ACTION_POINTER_DOWN (Second slot)
1895 const Point secondPoint = centerPoint + Point(100, 100);
1896 mDevice->sendSlot(SECOND_SLOT);
1897 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1898 mDevice->sendDown(secondPoint);
1899 mDevice->sendSync();
1900 assertReceivedMotion(ACTION_POINTER_1_DOWN, {centerPoint, secondPoint});
1901
1902 // ACTION_MOVE (First slot)
1903 mDevice->sendSlot(FIRST_SLOT);
1904 mDevice->sendMove(centerPoint + Point(5, 5));
1905 // ACTION_POINTER_UP (Second slot)
1906 mDevice->sendSlot(SECOND_SLOT);
1907 mDevice->sendMove(secondPoint + Point(6, 6));
1908 mDevice->sendPointerUp();
1909 // Send a single sync for the above 2 pointer updates
1910 mDevice->sendSync();
1911
1912 // First, we should get POINTER_UP for the second pointer
1913 // The movement of the second pointer during the liftoff frame is ignored.
1914 // The coordinates 'secondPoint + Point(6, 6)' are never sent to the listener.
1915 assertReceivedMotion(ACTION_POINTER_1_UP,
1916 {/*first pointer */ centerPoint + Point(5, 5),
1917 /*second pointer*/ secondPoint});
1918
1919 // Next, the MOVE event for the first pointer
1920 assertReceivedMotion(AMOTION_EVENT_ACTION_MOVE, {centerPoint + Point(5, 5)});
1921}
1922
Arpit Singh440bf652023-08-09 09:23:43 +00001923TEST_P(TouchIntegrationTest, InputEvent_ProcessPalm) {
Arthur Hungaab25622020-01-16 11:22:11 +08001924 NotifyMotionArgs args;
1925 const Point centerPoint = mDevice->getCenterPoint();
1926
1927 // ACTION_DOWN
arthurhungcc7f9802020-04-30 17:55:40 +08001928 mDevice->sendSlot(FIRST_SLOT);
1929 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001930 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001931 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001932 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1933 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1934
arthurhungcc7f9802020-04-30 17:55:40 +08001935 // ACTION_POINTER_DOWN (second slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001936 const Point secondPoint = centerPoint + Point(100, 100);
1937 mDevice->sendSlot(SECOND_SLOT);
1938 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1939 mDevice->sendDown(secondPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001940 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001941 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001942 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001943
arthurhungcc7f9802020-04-30 17:55:40 +08001944 // ACTION_MOVE (second slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001945 mDevice->sendMove(secondPoint + Point(1, 1));
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001946 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001947 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1948 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1949
arthurhungcc7f9802020-04-30 17:55:40 +08001950 // Send MT_TOOL_PALM (second slot), which indicates that the touch IC has determined this to be
1951 // a palm event.
1952 // Expect to receive the ACTION_POINTER_UP with cancel flag.
Arthur Hungaab25622020-01-16 11:22:11 +08001953 mDevice->sendToolType(MT_TOOL_PALM);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001954 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001955 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001956 ASSERT_EQ(ACTION_POINTER_1_UP, args.action);
arthurhungcc7f9802020-04-30 17:55:40 +08001957 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, args.flags);
Arthur Hungaab25622020-01-16 11:22:11 +08001958
arthurhungcc7f9802020-04-30 17:55:40 +08001959 // Send up to second slot, expect first slot send moving.
1960 mDevice->sendPointerUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001961 mDevice->sendSync();
arthurhungcc7f9802020-04-30 17:55:40 +08001962 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1963 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001964
arthurhungcc7f9802020-04-30 17:55:40 +08001965 // Send ACTION_UP (first slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001966 mDevice->sendSlot(FIRST_SLOT);
1967 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001968 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001969
arthurhungcc7f9802020-04-30 17:55:40 +08001970 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1971 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001972}
1973
Prabir Pradhanc09ec6d2023-08-14 22:31:43 +00001974/**
1975 * Some drivers historically have reported axis values outside of the range specified in the
1976 * evdev axis info. Ensure we don't crash when this happens. For example, a driver may report a
1977 * pressure value greater than the reported maximum, since it unclear what specific meaning the
1978 * maximum value for pressure has (beyond the maximum value that can be produced by a sensor),
1979 * and no units for pressure (resolution) is specified by the evdev documentation.
1980 */
1981TEST_P(TouchIntegrationTest, AcceptsAxisValuesOutsideReportedRange) {
1982 const Point centerPoint = mDevice->getCenterPoint();
1983
1984 // Down with pressure outside the reported range
1985 mDevice->sendSlot(FIRST_SLOT);
1986 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1987 mDevice->sendDown(centerPoint);
1988 mDevice->sendPressure(UinputTouchScreen::RAW_PRESSURE_MAX + 2);
1989 mDevice->sendSync();
1990 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1991 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
1992
1993 // Move to a point outside the reported range
1994 mDevice->sendMove(Point(DISPLAY_WIDTH, DISPLAY_HEIGHT) + Point(1, 1));
1995 mDevice->sendSync();
1996 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1997 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
1998
1999 // Up
2000 mDevice->sendUp();
2001 mDevice->sendSync();
2002 ASSERT_NO_FATAL_FAILURE(
2003 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2004}
2005
Arpit Singh440bf652023-08-09 09:23:43 +00002006TEST_P(TouchIntegrationTest, NotifiesPolicyWhenStylusGestureStarted) {
Prabir Pradhanda20b172022-09-26 17:01:18 +00002007 const Point centerPoint = mDevice->getCenterPoint();
2008
2009 // Send down with the pen tool selected. The policy should be notified of the stylus presence.
2010 mDevice->sendSlot(FIRST_SLOT);
2011 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2012 mDevice->sendToolType(MT_TOOL_PEN);
2013 mDevice->sendDown(centerPoint);
2014 mDevice->sendSync();
2015 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2016 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002017 WithToolType(ToolType::STYLUS))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00002018
2019 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotified(mDeviceInfo.getId()));
2020
2021 // Release the stylus touch.
2022 mDevice->sendUp();
2023 mDevice->sendSync();
2024 ASSERT_NO_FATAL_FAILURE(
2025 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2026
2027 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotNotified());
2028
2029 // Touch down with the finger, without the pen tool selected. The policy is not notified.
2030 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2031 mDevice->sendToolType(MT_TOOL_FINGER);
2032 mDevice->sendDown(centerPoint);
2033 mDevice->sendSync();
2034 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2035 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002036 WithToolType(ToolType::FINGER))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00002037
2038 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotNotified());
2039
2040 mDevice->sendUp();
2041 mDevice->sendSync();
2042 ASSERT_NO_FATAL_FAILURE(
2043 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2044
2045 // Send a move event with the stylus tool without BTN_TOUCH to generate a hover enter.
2046 // The policy should be notified of the stylus presence.
2047 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2048 mDevice->sendToolType(MT_TOOL_PEN);
2049 mDevice->sendMove(centerPoint);
2050 mDevice->sendSync();
2051 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2052 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002053 WithToolType(ToolType::STYLUS))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00002054
2055 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotified(mDeviceInfo.getId()));
2056}
2057
Arpit Singh440bf652023-08-09 09:23:43 +00002058TEST_P(TouchIntegrationTest, ExternalStylusConnectedDuringTouchGesture) {
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002059 const Point centerPoint = mDevice->getCenterPoint();
2060
2061 // Down
2062 mDevice->sendSlot(FIRST_SLOT);
2063 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2064 mDevice->sendDown(centerPoint);
2065 mDevice->sendSync();
2066 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2067 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
2068
2069 // Move
2070 mDevice->sendMove(centerPoint + Point(1, 1));
2071 mDevice->sendSync();
2072 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2073 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
2074
2075 // Connecting an external stylus mid-gesture should not interrupt the ongoing gesture stream.
2076 auto externalStylus = createUinputDevice<UinputExternalStylus>();
2077 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Liana Kazanovac3cf1a22024-07-18 17:18:21 +00002078 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002079 const auto stylusInfo = waitForDevice(externalStylus->getName());
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002080 ASSERT_TRUE(stylusInfo);
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002081
2082 // Move
2083 mDevice->sendMove(centerPoint + Point(2, 2));
2084 mDevice->sendSync();
2085 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2086 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
2087
2088 // Disconnecting an external stylus mid-gesture should not interrupt the ongoing gesture stream.
2089 externalStylus.reset();
2090 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Liana Kazanovac3cf1a22024-07-18 17:18:21 +00002091 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002092 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2093
2094 // Up
2095 mDevice->sendUp();
2096 mDevice->sendSync();
2097 ASSERT_NO_FATAL_FAILURE(
2098 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2099
2100 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2101}
2102
Arpit Singh440bf652023-08-09 09:23:43 +00002103INSTANTIATE_TEST_SUITE_P(TouchIntegrationTestDisplayVariants, TouchIntegrationTest,
2104 testing::Values(TouchIntegrationTestDisplays::DISPLAY_INTERNAL,
2105 TouchIntegrationTestDisplays::DISPLAY_INPUT_PORT,
2106 TouchIntegrationTestDisplays::DISPLAY_UNIQUE_ID));
2107
Prabir Pradhan124ea442022-10-28 20:27:44 +00002108// --- StylusButtonIntegrationTest ---
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002109
Prabir Pradhan124ea442022-10-28 20:27:44 +00002110// Verify the behavior of button presses reported by various kinds of styluses, including buttons
2111// reported by the touchscreen's device, by a fused external stylus, and by an un-fused external
2112// stylus.
2113template <typename UinputStylusDevice>
Arpit Singh440bf652023-08-09 09:23:43 +00002114class StylusButtonIntegrationTest : public BaseTouchIntegrationTest {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002115protected:
2116 void SetUp() override {
2117#if !defined(__ANDROID__)
2118 GTEST_SKIP();
2119#endif
Arpit Singh440bf652023-08-09 09:23:43 +00002120 BaseTouchIntegrationTest::SetUp();
Prabir Pradhan124ea442022-10-28 20:27:44 +00002121 mTouchscreen = mDevice.get();
2122 mTouchscreenInfo = mDeviceInfo;
2123
2124 setUpStylusDevice();
2125 }
2126
2127 UinputStylusDevice* mStylus{nullptr};
2128 InputDeviceInfo mStylusInfo{};
2129
2130 UinputTouchScreen* mTouchscreen{nullptr};
2131 InputDeviceInfo mTouchscreenInfo{};
2132
2133private:
2134 // When we are attempting to test stylus button events that are sent from the touchscreen,
2135 // use the same Uinput device for the touchscreen and the stylus.
2136 template <typename T = UinputStylusDevice>
2137 std::enable_if_t<std::is_same_v<UinputTouchScreen, T>, void> setUpStylusDevice() {
2138 mStylus = mDevice.get();
2139 mStylusInfo = mDeviceInfo;
2140 }
2141
2142 // When we are attempting to stylus buttons from an external stylus being merged with touches
2143 // from a touchscreen, create a new Uinput device through which stylus buttons can be injected.
2144 template <typename T = UinputStylusDevice>
2145 std::enable_if_t<!std::is_same_v<UinputTouchScreen, T>, void> setUpStylusDevice() {
2146 mStylusDeviceLifecycleTracker = createUinputDevice<T>();
2147 mStylus = mStylusDeviceLifecycleTracker.get();
2148 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Liana Kazanovac3cf1a22024-07-18 17:18:21 +00002149 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
2150 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002151 const auto info = waitForDevice(mStylus->getName());
Prabir Pradhan124ea442022-10-28 20:27:44 +00002152 ASSERT_TRUE(info);
2153 mStylusInfo = *info;
2154 }
2155
2156 std::unique_ptr<UinputStylusDevice> mStylusDeviceLifecycleTracker{};
2157
2158 // Hide the base class's device to expose it with a different name for readability.
Arpit Singh440bf652023-08-09 09:23:43 +00002159 using BaseTouchIntegrationTest::mDevice;
2160 using BaseTouchIntegrationTest::mDeviceInfo;
Prabir Pradhan124ea442022-10-28 20:27:44 +00002161};
2162
2163using StylusButtonIntegrationTestTypes =
2164 ::testing::Types<UinputTouchScreen, UinputExternalStylus, UinputExternalStylusWithPressure>;
2165TYPED_TEST_SUITE(StylusButtonIntegrationTest, StylusButtonIntegrationTestTypes);
2166
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002167TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsGenerateKeyEvents) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002168 const auto stylusId = TestFixture::mStylusInfo.getId();
2169
2170 TestFixture::mStylus->pressKey(BTN_STYLUS);
2171 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2172 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2173 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2174
2175 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2176 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002177 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002178 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002179}
2180
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002181TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingTouchGesture) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002182 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2183 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2184 const auto stylusId = TestFixture::mStylusInfo.getId();
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002185
2186 // Press the stylus button.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002187 TestFixture::mStylus->pressKey(BTN_STYLUS);
2188 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002189 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002190 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002191
2192 // Start and finish a stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002193 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2194 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2195 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2196 TestFixture::mTouchscreen->sendDown(centerPoint);
2197 TestFixture::mTouchscreen->sendSync();
2198 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002199 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002200 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002201 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2202 WithDeviceId(touchscreenId))));
2203 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002204 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002205 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002206 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2207 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002208
Prabir Pradhan124ea442022-10-28 20:27:44 +00002209 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2210 TestFixture::mTouchscreen->sendSync();
2211 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002212 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002213 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002214 WithDeviceId(touchscreenId))));
2215 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002216 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002217 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002218 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002219
2220 // Release the stylus button.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002221 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2222 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002223 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002224 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002225}
2226
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002227TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingHoveringTouchGesture) {
Prabir Pradhan9a561c22022-11-07 16:11:23 +00002228 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2229 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2230 const auto stylusId = TestFixture::mStylusInfo.getId();
2231 auto toolTypeDevice =
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002232 AllOf(WithToolType(ToolType::STYLUS), WithDeviceId(touchscreenId));
Prabir Pradhan9a561c22022-11-07 16:11:23 +00002233
2234 // Press the stylus button.
2235 TestFixture::mStylus->pressKey(BTN_STYLUS);
2236 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2237 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2238 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2239
2240 // Start hovering with the stylus.
2241 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2242 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2243 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2244 TestFixture::mTouchscreen->sendMove(centerPoint);
2245 TestFixture::mTouchscreen->sendSync();
2246 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2247 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2248 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2249 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2250 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2251 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2252 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2253 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
2254 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2255
2256 // Touch down with the stylus.
2257 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2258 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2259 TestFixture::mTouchscreen->sendDown(centerPoint);
2260 TestFixture::mTouchscreen->sendSync();
2261 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2262 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
2263 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2264
2265 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2266 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
2267 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2268
2269 // Stop touching with the stylus, and start hovering.
2270 TestFixture::mTouchscreen->sendUp();
2271 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2272 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2273 TestFixture::mTouchscreen->sendMove(centerPoint);
2274 TestFixture::mTouchscreen->sendSync();
2275 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2276 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_UP),
2277 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2278 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2279 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2280 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2281 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2282 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2283 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2284
2285 // Stop hovering.
2286 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2287 TestFixture::mTouchscreen->sendSync();
2288 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2289 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
2290 WithButtonState(0))));
2291 // TODO(b/257971675): Fix inconsistent button state when exiting hover.
2292 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2293 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
2294 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2295
2296 // Release the stylus button.
2297 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2298 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2299 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
2300 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2301}
2302
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002303TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsWithinTouchGesture) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002304 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2305 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2306 const auto stylusId = TestFixture::mStylusInfo.getId();
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002307
2308 // Start a stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002309 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2310 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2311 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2312 TestFixture::mTouchscreen->sendDown(centerPoint);
2313 TestFixture::mTouchscreen->sendSync();
2314 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002315 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002316 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002317 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002318
2319 // Press and release a stylus button. Each change in button state also generates a MOVE event.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002320 TestFixture::mStylus->pressKey(BTN_STYLUS);
2321 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002322 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002323 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2324 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002325 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002326 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002327 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2328 WithDeviceId(touchscreenId))));
2329 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002330 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002331 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002332 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2333 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002334
Prabir Pradhan124ea442022-10-28 20:27:44 +00002335 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2336 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002337 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002338 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2339 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002340 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002341 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002342 WithDeviceId(touchscreenId))));
2343 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002344 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002345 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002346 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002347
2348 // Finish the stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002349 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2350 TestFixture::mTouchscreen->sendSync();
2351 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002352 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002353 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002354 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002355}
2356
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002357TYPED_TEST(StylusButtonIntegrationTest, StylusButtonMotionEventsDisabled) {
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002358 TestFixture::mFakePolicy->setStylusButtonMotionEventsEnabled(false);
2359 TestFixture::mReader->requestRefreshConfiguration(
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002360 InputReaderConfiguration::Change::STYLUS_BUTTON_REPORTING);
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002361
2362 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2363 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2364 const auto stylusId = TestFixture::mStylusInfo.getId();
2365
2366 // Start a stylus gesture. By the time this event is processed, the configuration change that
2367 // was requested is guaranteed to be completed.
2368 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2369 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2370 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2371 TestFixture::mTouchscreen->sendDown(centerPoint);
2372 TestFixture::mTouchscreen->sendSync();
2373 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2374 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002375 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002376 WithDeviceId(touchscreenId))));
2377
2378 // Press and release a stylus button. Each change only generates a MOVE motion event.
2379 // Key events are unaffected.
2380 TestFixture::mStylus->pressKey(BTN_STYLUS);
2381 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2382 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2383 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2384 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2385 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002386 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002387 WithDeviceId(touchscreenId))));
2388
2389 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2390 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2391 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
2392 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2393 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2394 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002395 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002396 WithDeviceId(touchscreenId))));
2397
2398 // Finish the stylus gesture.
2399 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2400 TestFixture::mTouchscreen->sendSync();
2401 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2402 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002403 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002404 WithDeviceId(touchscreenId))));
2405}
2406
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002407// --- ExternalStylusIntegrationTest ---
2408
2409// Verify the behavior of an external stylus. An external stylus can report pressure or button
2410// data independently of the touchscreen, which is then sent as a MotionEvent as part of an
2411// ongoing stylus gesture that is being emitted by the touchscreen.
Arpit Singh440bf652023-08-09 09:23:43 +00002412using ExternalStylusIntegrationTest = BaseTouchIntegrationTest;
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002413
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002414TEST_F(ExternalStylusIntegrationTest, ExternalStylusConnectionChangesTouchscreenSource) {
2415 // Create an external stylus capable of reporting pressure data that
2416 // should be fused with a touch pointer.
2417 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2418 createUinputDevice<UinputExternalStylusWithPressure>();
2419 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Liana Kazanovac3cf1a22024-07-18 17:18:21 +00002420 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002421 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002422 ASSERT_TRUE(stylusInfo);
2423
2424 // Connecting an external stylus changes the source of the touchscreen.
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002425 const auto deviceInfo = waitForDevice(mDevice->getName());
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002426 ASSERT_TRUE(deviceInfo);
2427 ASSERT_TRUE(isFromSource(deviceInfo->getSources(), STYLUS_FUSION_SOURCE));
2428}
2429
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002430TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureReported) {
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002431 const Point centerPoint = mDevice->getCenterPoint();
2432
2433 // Create an external stylus capable of reporting pressure data that
2434 // should be fused with a touch pointer.
2435 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2436 createUinputDevice<UinputExternalStylusWithPressure>();
2437 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Liana Kazanovac3cf1a22024-07-18 17:18:21 +00002438 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002439 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002440 ASSERT_TRUE(stylusInfo);
2441
2442 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2443
2444 const auto touchscreenId = mDeviceInfo.getId();
2445
2446 // Set a pressure value on the stylus. It doesn't generate any events.
2447 const auto& RAW_PRESSURE_MAX = UinputExternalStylusWithPressure::RAW_PRESSURE_MAX;
2448 stylus->setPressure(100);
2449 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2450
2451 // Start a finger gesture, and ensure it shows up as stylus gesture
2452 // with the pressure set by the external stylus.
Dominik Laskowski2f01d772022-03-23 16:01:29 -07002453 mDevice->sendSlot(FIRST_SLOT);
Chris Ye1b0c7342020-07-28 21:57:03 -07002454 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002455 mDevice->sendToolType(MT_TOOL_FINGER);
Prabir Pradhanb54ffb22022-10-27 18:03:34 +00002456 mDevice->sendDown(centerPoint);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002457 mDevice->sendSync();
2458 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002459 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithToolType(ToolType::STYLUS),
2460 WithButtonState(0), WithSource(STYLUS_FUSION_SOURCE), WithDeviceId(touchscreenId),
2461 WithPressure(100.f / RAW_PRESSURE_MAX))));
Dominik Laskowski2f01d772022-03-23 16:01:29 -07002462
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002463 // Change the pressure on the external stylus, and ensure the touchscreen generates a MOVE
2464 // event with the updated pressure.
2465 stylus->setPressure(200);
Vaibhav Devmuraridd82b8e2022-08-16 15:34:01 +00002466 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002467 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithToolType(ToolType::STYLUS),
2468 WithButtonState(0), WithSource(STYLUS_FUSION_SOURCE), WithDeviceId(touchscreenId),
2469 WithPressure(200.f / RAW_PRESSURE_MAX))));
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002470
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002471 // The external stylus did not generate any events.
2472 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2473 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
2474}
2475
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002476TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureNotReported) {
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002477 const Point centerPoint = mDevice->getCenterPoint();
2478
2479 // Create an external stylus capable of reporting pressure data that
2480 // should be fused with a touch pointer.
2481 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2482 createUinputDevice<UinputExternalStylusWithPressure>();
2483 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Liana Kazanovac3cf1a22024-07-18 17:18:21 +00002484 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002485 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002486 ASSERT_TRUE(stylusInfo);
2487
2488 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2489
2490 const auto touchscreenId = mDeviceInfo.getId();
2491
2492 // Set a pressure value of 0 on the stylus. It doesn't generate any events.
2493 const auto& RAW_PRESSURE_MAX = UinputExternalStylusWithPressure::RAW_PRESSURE_MAX;
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002494 // Send a non-zero value first to prevent the kernel from consuming the zero event.
2495 stylus->setPressure(100);
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002496 stylus->setPressure(0);
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002497 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002498
2499 // Start a finger gesture. The touch device will withhold generating any touches for
2500 // up to 72 milliseconds while waiting for pressure data from the external stylus.
2501 mDevice->sendSlot(FIRST_SLOT);
2502 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2503 mDevice->sendToolType(MT_TOOL_FINGER);
2504 mDevice->sendDown(centerPoint);
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002505 const auto syncTime = std::chrono::system_clock::now();
2506 // After 72 ms, the event *will* be generated. If we wait the full 72 ms to check that NO event
2507 // is generated in that period, there will be a race condition between the event being generated
2508 // and the test's wait timeout expiring. Thus, we wait for a shorter duration in the test, which
2509 // will reduce the liklihood of the race condition occurring.
2510 const auto waitUntilTimeForNoEvent =
2511 syncTime + std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT / 2));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07002512 mDevice->sendSync();
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002513 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled(waitUntilTimeForNoEvent));
Michael Wrightd02c5b62014-02-10 15:10:22 -08002514
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002515 // Since the external stylus did not report a pressure value within the timeout,
2516 // it shows up as a finger pointer.
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002517 const auto waitUntilTimeForEvent = syncTime +
2518 std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT)) + EVENT_HAPPENED_TIMEOUT;
2519 ASSERT_NO_FATAL_FAILURE(
2520 mTestListener->assertNotifyMotionWasCalled(AllOf(WithMotionAction(
2521 AMOTION_EVENT_ACTION_DOWN),
2522 WithSource(AINPUT_SOURCE_TOUCHSCREEN |
2523 AINPUT_SOURCE_STYLUS),
2524 WithToolType(ToolType::FINGER),
2525 WithDeviceId(touchscreenId),
2526 WithPressure(1.f)),
2527 waitUntilTimeForEvent));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002528
2529 // Change the pressure on the external stylus. Since the pressure was not present at the start
2530 // of the gesture, it is ignored for now.
2531 stylus->setPressure(200);
2532 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2533
2534 // Finish the finger gesture.
Michael Wrightd02c5b62014-02-10 15:10:22 -08002535 mDevice->sendTrackingId(INVALID_TRACKING_ID);
2536 mDevice->sendSync();
2537 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2538 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002539 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002540 WithToolType(ToolType::FINGER))));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002541
2542 // Start a new gesture. Since we have a valid pressure value, it shows up as a stylus.
2543 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2544 mDevice->sendToolType(MT_TOOL_FINGER);
2545 mDevice->sendDown(centerPoint);
2546 mDevice->sendSync();
2547 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002548 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithSource(STYLUS_FUSION_SOURCE),
2549 WithToolType(ToolType::STYLUS), WithButtonState(0), WithDeviceId(touchscreenId),
2550 WithPressure(200.f / RAW_PRESSURE_MAX))));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002551
2552 // The external stylus did not generate any events.
2553 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2554 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002555}
Siarhei Vishniakou1983a712021-06-04 19:27:09 +00002556
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002557TEST_F(ExternalStylusIntegrationTest, UnfusedExternalStylus) {
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002558 const Point centerPoint = mDevice->getCenterPoint();
2559
2560 // Create an external stylus device that does not support pressure. It should not affect any
2561 // touch pointers.
2562 std::unique_ptr<UinputExternalStylus> stylus = createUinputDevice<UinputExternalStylus>();
2563 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Liana Kazanovac3cf1a22024-07-18 17:18:21 +00002564 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002565 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002566 ASSERT_TRUE(stylusInfo);
2567
2568 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2569
2570 const auto touchscreenId = mDeviceInfo.getId();
2571
2572 // Start a finger gesture and ensure a finger pointer is generated for it, without waiting for
2573 // pressure data from the external stylus.
2574 mDevice->sendSlot(FIRST_SLOT);
2575 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2576 mDevice->sendToolType(MT_TOOL_FINGER);
2577 mDevice->sendDown(centerPoint);
2578 auto waitUntil = std::chrono::system_clock::now() +
2579 std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT));
2580 mDevice->sendSync();
2581 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002582 mTestListener->assertNotifyMotionWasCalled(AllOf(WithMotionAction(
2583 AMOTION_EVENT_ACTION_DOWN),
2584 WithToolType(ToolType::FINGER),
2585 WithSource(AINPUT_SOURCE_TOUCHSCREEN |
2586 AINPUT_SOURCE_STYLUS),
2587 WithButtonState(0),
2588 WithDeviceId(touchscreenId),
2589 WithPressure(1.f)),
2590 waitUntil));
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002591
2592 // The external stylus did not generate any events.
2593 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2594 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
2595}
2596
Michael Wrightd02c5b62014-02-10 15:10:22 -08002597// --- InputDeviceTest ---
2598class InputDeviceTest : public testing::Test {
2599protected:
2600 static const char* DEVICE_NAME;
2601 static const char* DEVICE_LOCATION;
2602 static const int32_t DEVICE_ID;
2603 static const int32_t DEVICE_GENERATION;
2604 static const int32_t DEVICE_CONTROLLER_NUMBER;
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002605 static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002606 static const int32_t EVENTHUB_ID;
2607 static const std::string DEVICE_BLUETOOTH_ADDRESS;
2608
2609 std::shared_ptr<FakeEventHub> mFakeEventHub;
2610 sp<FakeInputReaderPolicy> mFakePolicy;
2611 std::unique_ptr<TestInputListener> mFakeListener;
2612 std::unique_ptr<InstrumentedInputReader> mReader;
2613 std::shared_ptr<InputDevice> mDevice;
2614
2615 void SetUp() override {
2616 mFakeEventHub = std::make_unique<FakeEventHub>();
2617 mFakePolicy = sp<FakeInputReaderPolicy>::make();
2618 mFakeListener = std::make_unique<TestInputListener>();
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002619 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Michael Wrightd02c5b62014-02-10 15:10:22 -08002620 *mFakeListener);
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002621 InputDeviceIdentifier identifier;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002622 identifier.name = DEVICE_NAME;
2623 identifier.location = DEVICE_LOCATION;
2624 identifier.bluetoothAddress = DEVICE_BLUETOOTH_ADDRESS;
2625 mDevice = std::make_shared<InputDevice>(mReader->getContext(), DEVICE_ID, DEVICE_GENERATION,
2626 identifier);
2627 mReader->pushNextDevice(mDevice);
2628 mFakeEventHub->addDevice(EVENTHUB_ID, DEVICE_NAME, ftl::Flags<InputDeviceClass>(0));
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002629 mReader->loopOnce();
Michael Wrightd02c5b62014-02-10 15:10:22 -08002630 }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002631
2632 void TearDown() override {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002633 mFakeListener.reset();
2634 mFakePolicy.clear();
2635 }
2636};
2637
2638const char* InputDeviceTest::DEVICE_NAME = "device";
2639const char* InputDeviceTest::DEVICE_LOCATION = "USB1";
2640const int32_t InputDeviceTest::DEVICE_ID = END_RESERVED_ID + 1000;
2641const int32_t InputDeviceTest::DEVICE_GENERATION = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002642const int32_t InputDeviceTest::DEVICE_CONTROLLER_NUMBER = 0;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002643const ftl::Flags<InputDeviceClass> InputDeviceTest::DEVICE_CLASSES =
2644 InputDeviceClass::KEYBOARD | InputDeviceClass::TOUCH | InputDeviceClass::JOYSTICK;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002645const int32_t InputDeviceTest::EVENTHUB_ID = 1;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002646const std::string InputDeviceTest::DEVICE_BLUETOOTH_ADDRESS = "11:AA:22:BB:33:CC";
2647
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002648TEST_F(InputDeviceTest, ImmutableProperties) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002649 ASSERT_EQ(DEVICE_ID, mDevice->getId());
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002650 ASSERT_STREQ(DEVICE_NAME, mDevice->getName().c_str());
2651 ASSERT_EQ(ftl::Flags<InputDeviceClass>(0), mDevice->getClasses());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002652}
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002653
Michael Wrightd02c5b62014-02-10 15:10:22 -08002654TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsFalse) {
2655 ASSERT_EQ(mDevice->isEnabled(), false);
2656}
2657
2658TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
2659 // Configuration.
2660 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002661 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002662
2663 // Reset.
2664 unused += mDevice->reset(ARBITRARY_TIME);
2665
2666 NotifyDeviceResetArgs resetArgs;
2667 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
2668 ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
2669 ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
2670
2671 // Metadata.
2672 ASSERT_TRUE(mDevice->isIgnored());
2673 ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mDevice->getSources());
2674
2675 InputDeviceInfo info = mDevice->getDeviceInfo();
2676 ASSERT_EQ(DEVICE_ID, info.getId());
2677 ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.c_str());
2678 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NONE, info.getKeyboardType());
2679 ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, info.getSources());
2680
2681 // State queries.
2682 ASSERT_EQ(0, mDevice->getMetaState());
2683
2684 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, 0))
2685 << "Ignored device should return unknown key code state.";
2686 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 0))
2687 << "Ignored device should return unknown scan code state.";
2688 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 0))
2689 << "Ignored device should return unknown switch state.";
2690
2691 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B};
2692 uint8_t flags[2] = { 0, 1 };
2693 ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, keyCodes, flags))
2694 << "Ignored device should never mark any key codes.";
2695 ASSERT_EQ(0, flags[0]) << "Flag for unsupported key should be unchanged.";
2696 ASSERT_EQ(1, flags[1]) << "Flag for unsupported key should be unchanged.";
2697}
2698
2699TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRequestsToMappers) {
2700 // Configuration.
2701 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "key", "value");
2702
2703 FakeInputMapper& mapper1 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00002704 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2705 AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002706 mapper1.setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC);
2707 mapper1.setMetaState(AMETA_ALT_ON);
2708 mapper1.addSupportedKeyCode(AKEYCODE_A);
2709 mapper1.addSupportedKeyCode(AKEYCODE_B);
2710 mapper1.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
2711 mapper1.setKeyCodeState(AKEYCODE_B, AKEY_STATE_UP);
2712 mapper1.setScanCodeState(2, AKEY_STATE_DOWN);
2713 mapper1.setScanCodeState(3, AKEY_STATE_UP);
2714 mapper1.setSwitchState(4, AKEY_STATE_DOWN);
2715
2716 FakeInputMapper& mapper2 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00002717 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2718 AINPUT_SOURCE_TOUCHSCREEN);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002719 mapper2.setMetaState(AMETA_SHIFT_ON);
2720
2721 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002722 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002723
Harry Cuttsf13161a2023-03-08 14:15:49 +00002724 std::optional<std::string> propertyValue = mDevice->getConfiguration().getString("key");
2725 ASSERT_TRUE(propertyValue.has_value())
Michael Wrightd02c5b62014-02-10 15:10:22 -08002726 << "Device should have read configuration during configuration phase.";
Harry Cuttsf13161a2023-03-08 14:15:49 +00002727 ASSERT_EQ("value", *propertyValue);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002728
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002729 ASSERT_NO_FATAL_FAILURE(mapper1.assertConfigureWasCalled());
2730 ASSERT_NO_FATAL_FAILURE(mapper2.assertConfigureWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002731
2732 // Reset
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002733 unused += mDevice->reset(ARBITRARY_TIME);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002734 ASSERT_NO_FATAL_FAILURE(mapper1.assertResetWasCalled());
2735 ASSERT_NO_FATAL_FAILURE(mapper2.assertResetWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002736
2737 NotifyDeviceResetArgs resetArgs;
2738 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
2739 ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
2740 ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
2741
2742 // Metadata.
2743 ASSERT_FALSE(mDevice->isIgnored());
2744 ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), mDevice->getSources());
2745
Siarhei Vishniakou1983a712021-06-04 19:27:09 +00002746 InputDeviceInfo info = mDevice->getDeviceInfo();
Michael Wrightd02c5b62014-02-10 15:10:22 -08002747 ASSERT_EQ(DEVICE_ID, info.getId());
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002748 ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002749 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, info.getKeyboardType());
2750 ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), info.getSources());
2751
2752 // State queries.
2753 ASSERT_EQ(AMETA_ALT_ON | AMETA_SHIFT_ON, mDevice->getMetaState())
2754 << "Should query mappers and combine meta states.";
2755
2756 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2757 << "Should return unknown key code state when source not supported.";
2758 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2759 << "Should return unknown scan code state when source not supported.";
2760 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2761 << "Should return unknown switch state when source not supported.";
2762
2763 ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, AKEYCODE_A))
2764 << "Should query mapper when source is supported.";
2765 ASSERT_EQ(AKEY_STATE_UP, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 3))
2766 << "Should query mapper when source is supported.";
2767 ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 4))
2768 << "Should query mapper when source is supported.";
2769
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002770 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2};
Michael Wrightd02c5b62014-02-10 15:10:22 -08002771 uint8_t flags[4] = { 0, 0, 0, 1 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002772 ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -08002773 << "Should do nothing when source is unsupported.";
2774 ASSERT_EQ(0, flags[0]) << "Flag should be unchanged when source is unsupported.";
2775 ASSERT_EQ(0, flags[1]) << "Flag should be unchanged when source is unsupported.";
2776 ASSERT_EQ(0, flags[2]) << "Flag should be unchanged when source is unsupported.";
2777 ASSERT_EQ(1, flags[3]) << "Flag should be unchanged when source is unsupported.";
2778
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002779 ASSERT_TRUE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -08002780 << "Should query mapper when source is supported.";
2781 ASSERT_EQ(1, flags[0]) << "Flag for supported key should be set.";
2782 ASSERT_EQ(1, flags[1]) << "Flag for supported key should be set.";
2783 ASSERT_EQ(0, flags[2]) << "Flag for unsupported key should be unchanged.";
2784 ASSERT_EQ(1, flags[3]) << "Flag for unsupported key should be unchanged.";
2785
2786 // Event handling.
2787 RawEvent event;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002788 event.deviceId = EVENTHUB_ID;
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002789 unused += mDevice->process(&event, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002790
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002791 ASSERT_NO_FATAL_FAILURE(mapper1.assertProcessWasCalled());
2792 ASSERT_NO_FATAL_FAILURE(mapper2.assertProcessWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002793}
2794
Yeabkal Wubshitb1b96db2024-01-24 12:47:00 -08002795TEST_F(InputDeviceTest, Configure_SmoothScrollViewBehaviorNotSet) {
2796 // Set some behavior to force the configuration to be update.
2797 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "1");
2798 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2799 AINPUT_SOURCE_KEYBOARD);
2800
2801 std::list<NotifyArgs> unused =
2802 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2803 /*changes=*/{});
2804
2805 ASSERT_FALSE(mDevice->getDeviceInfo().getViewBehavior().shouldSmoothScroll.has_value());
2806}
2807
2808TEST_F(InputDeviceTest, Configure_SmoothScrollViewBehaviorEnabled) {
2809 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.viewBehavior_smoothScroll", "1");
2810 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2811 AINPUT_SOURCE_KEYBOARD);
2812
2813 std::list<NotifyArgs> unused =
2814 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2815 /*changes=*/{});
2816
2817 ASSERT_TRUE(mDevice->getDeviceInfo().getViewBehavior().shouldSmoothScroll.value_or(false));
2818}
2819
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -07002820TEST_F(InputDeviceTest, WakeDevice_AddsWakeFlagToProcessNotifyArgs) {
2821 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "1");
2822 FakeInputMapper& mapper =
2823 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2824 AINPUT_SOURCE_KEYBOARD);
2825 NotifyMotionArgs args1;
2826 NotifySwitchArgs args2;
2827 NotifyKeyArgs args3;
2828 mapper.setProcessResult({args1, args2, args3});
2829
2830 InputReaderConfiguration config;
2831 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2832
2833 RawEvent event;
2834 event.deviceId = EVENTHUB_ID;
2835 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2836
2837 for (auto& arg : notifyArgs) {
2838 if (const auto notifyMotionArgs = std::get_if<NotifyMotionArgs>(&arg)) {
2839 ASSERT_EQ(POLICY_FLAG_WAKE, notifyMotionArgs->policyFlags);
2840 } else if (const auto notifySwitchArgs = std::get_if<NotifySwitchArgs>(&arg)) {
2841 ASSERT_EQ(POLICY_FLAG_WAKE, notifySwitchArgs->policyFlags);
2842 } else if (const auto notifyKeyArgs = std::get_if<NotifyKeyArgs>(&arg)) {
2843 ASSERT_EQ(POLICY_FLAG_WAKE, notifyKeyArgs->policyFlags);
2844 }
2845 }
2846}
2847
2848TEST_F(InputDeviceTest, NotWakeDevice_DoesNotAddWakeFlagToProcessNotifyArgs) {
2849 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "0");
2850 FakeInputMapper& mapper =
2851 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2852 AINPUT_SOURCE_KEYBOARD);
2853 NotifyMotionArgs args;
2854 mapper.setProcessResult({args});
2855
2856 InputReaderConfiguration config;
2857 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2858
2859 RawEvent event;
2860 event.deviceId = EVENTHUB_ID;
2861 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2862
2863 // POLICY_FLAG_WAKE is not added to the NotifyArgs.
2864 ASSERT_EQ(0u, std::get<NotifyMotionArgs>(notifyArgs.front()).policyFlags);
2865}
2866
2867TEST_F(InputDeviceTest, NotWakeDevice_DoesNotRemoveExistingWakeFlagFromProcessNotifyArgs) {
2868 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "0");
2869 FakeInputMapper& mapper =
2870 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2871 AINPUT_SOURCE_KEYBOARD);
2872 NotifyMotionArgs args;
2873 args.policyFlags = POLICY_FLAG_WAKE;
2874 mapper.setProcessResult({args});
2875
2876 InputReaderConfiguration config;
2877 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2878
2879 RawEvent event;
2880 event.deviceId = EVENTHUB_ID;
2881 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2882
2883 // The POLICY_FLAG_WAKE is preserved, despite the device being a non-wake device.
2884 ASSERT_EQ(POLICY_FLAG_WAKE, std::get<NotifyMotionArgs>(notifyArgs.front()).policyFlags);
2885}
2886
Arthur Hung2c9a3342019-07-23 14:18:59 +08002887// A single input device is associated with a specific display. Check that:
2888// 1. Device is disabled if the viewport corresponding to the associated display is not found
Arpit Singh48189772023-05-30 14:12:49 +00002889// 2. Device is disabled when configure API is called
Arthur Hung2c9a3342019-07-23 14:18:59 +08002890TEST_F(InputDeviceTest, Configure_AssignsDisplayPort) {
Arpit Singh8e6fb252023-04-06 11:49:17 +00002891 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2892 AINPUT_SOURCE_TOUCHSCREEN);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002893
2894 // First Configuration.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002895 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002896 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2897 /*changes=*/{});
Arthur Hung2c9a3342019-07-23 14:18:59 +08002898
2899 // Device should be enabled by default.
2900 ASSERT_TRUE(mDevice->isEnabled());
2901
2902 // Prepare associated info.
2903 constexpr uint8_t hdmi = 1;
2904 const std::string UNIQUE_ID = "local:1";
2905
2906 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002907 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002908 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002909 // Device should be disabled because it is associated with a specific display via
2910 // input port <-> display port association, but the corresponding display is not found
2911 ASSERT_FALSE(mDevice->isEnabled());
2912
2913 // Prepare displays.
2914 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +00002915 ui::ROTATION_0, /*isActive=*/true, UNIQUE_ID, hdmi,
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00002916 ViewportType::INTERNAL);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002917 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002918 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002919 ASSERT_TRUE(mDevice->isEnabled());
2920
2921 // Device should be disabled after set disable.
2922 mFakePolicy->addDisabledDevice(mDevice->getId());
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002923 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002924 InputReaderConfiguration::Change::ENABLED_STATE);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002925 ASSERT_FALSE(mDevice->isEnabled());
2926
2927 // Device should still be disabled even found the associated display.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002928 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002929 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002930 ASSERT_FALSE(mDevice->isEnabled());
2931}
Michael Wrightd02c5b62014-02-10 15:10:22 -08002932
Christine Franks1ba71cc2021-04-07 14:37:42 -07002933TEST_F(InputDeviceTest, Configure_AssignsDisplayUniqueId) {
2934 // Device should be enabled by default.
2935 mFakePolicy->clearViewports();
Arpit Singh8e6fb252023-04-06 11:49:17 +00002936 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2937 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002938 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002939 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2940 /*changes=*/{});
Christine Franks1ba71cc2021-04-07 14:37:42 -07002941 ASSERT_TRUE(mDevice->isEnabled());
2942
2943 // Device should be disabled because it is associated with a specific display, but the
2944 // corresponding display is not found.
Christine Franks2a2293c2022-01-18 11:51:16 -08002945 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002946 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002947 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002948 ASSERT_FALSE(mDevice->isEnabled());
2949
2950 // Device should be enabled when a display is found.
2951 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00002952 ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
Christine Franks1ba71cc2021-04-07 14:37:42 -07002953 NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002954 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002955 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002956 ASSERT_TRUE(mDevice->isEnabled());
2957
2958 // Device should be disabled after set disable.
2959 mFakePolicy->addDisabledDevice(mDevice->getId());
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002960 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002961 InputReaderConfiguration::Change::ENABLED_STATE);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002962 ASSERT_FALSE(mDevice->isEnabled());
2963
2964 // Device should still be disabled even found the associated display.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002965 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002966 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002967 ASSERT_FALSE(mDevice->isEnabled());
2968}
2969
Christine Franks2a2293c2022-01-18 11:51:16 -08002970TEST_F(InputDeviceTest, Configure_UniqueId_CorrectlyMatches) {
2971 mFakePolicy->clearViewports();
Arpit Singh8e6fb252023-04-06 11:49:17 +00002972 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2973 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002974 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002975 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2976 /*changes=*/{});
Christine Franks2a2293c2022-01-18 11:51:16 -08002977
Christine Franks2a2293c2022-01-18 11:51:16 -08002978 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
2979 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00002980 ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
Christine Franks2a2293c2022-01-18 11:51:16 -08002981 NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan55c5ee22024-02-14 06:03:02 +00002982 const auto initialGeneration = mDevice->getGeneration();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002983 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002984 InputReaderConfiguration::Change::DISPLAY_INFO);
Antonio Kantek0ac5e092024-04-22 17:10:27 +00002985 ASSERT_EQ(DISPLAY_UNIQUE_ID, mDevice->getAssociatedDisplayUniqueIdByPort());
Prabir Pradhan55c5ee22024-02-14 06:03:02 +00002986 ASSERT_GT(mDevice->getGeneration(), initialGeneration);
2987 ASSERT_EQ(mDevice->getDeviceInfo().getAssociatedDisplayId(), SECONDARY_DISPLAY_ID);
Christine Franks2a2293c2022-01-18 11:51:16 -08002988}
2989
Siarhei Vishniakou30feb8c2022-09-28 10:48:29 -07002990/**
2991 * This test reproduces a crash caused by a dangling reference that remains after device is added
2992 * and removed. The reference is accessed in InputDevice::dump(..);
2993 */
2994TEST_F(InputDeviceTest, DumpDoesNotCrash) {
2995 constexpr int32_t TEST_EVENTHUB_ID = 10;
2996 mFakeEventHub->addDevice(TEST_EVENTHUB_ID, "Test EventHub device", InputDeviceClass::BATTERY);
2997
Harry Cutts33476232023-01-30 19:57:29 +00002998 InputDevice device(mReader->getContext(), /*id=*/1, /*generation=*/2, /*identifier=*/{});
Arpit Singh82f29a12023-06-13 15:05:53 +00002999 auto _ = device.addEventHubDevice(ARBITRARY_TIME, TEST_EVENTHUB_ID,
3000 mFakePolicy->getReaderConfiguration());
Siarhei Vishniakou30feb8c2022-09-28 10:48:29 -07003001 device.removeEventHubDevice(TEST_EVENTHUB_ID);
3002 std::string dumpStr, eventHubDevStr;
3003 device.dump(dumpStr, eventHubDevStr);
3004}
3005
Prabir Pradhanb54ffb22022-10-27 18:03:34 +00003006TEST_F(InputDeviceTest, GetBluetoothAddress) {
3007 const auto& address = mReader->getBluetoothAddress(DEVICE_ID);
3008 ASSERT_TRUE(address);
3009 ASSERT_EQ(DEVICE_BLUETOOTH_ADDRESS, *address);
3010}
3011
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003012TEST_F(InputDeviceTest, KernelBufferOverflowResetsMappers) {
3013 mFakePolicy->clearViewports();
3014 FakeInputMapper& mapper =
3015 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
3016 AINPUT_SOURCE_KEYBOARD);
3017 std::list<NotifyArgs> unused =
3018 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
3019 /*changes=*/{});
3020
3021 mapper.assertConfigureWasCalled();
3022 mapper.assertResetWasNotCalled();
3023
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -08003024 RawEvent event{.when = ARBITRARY_TIME,
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003025 .readTime = ARBITRARY_TIME,
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -08003026 .deviceId = EVENTHUB_ID,
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003027 .type = EV_SYN,
3028 .code = SYN_REPORT,
3029 .value = 0};
3030
3031 // Events are processed normally.
3032 unused = mDevice->process(&event, /*count=*/1);
3033 mapper.assertProcessWasCalled();
3034
3035 // Simulate a kernel buffer overflow, which generates a SYN_DROPPED event.
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003036 event.type = EV_SYN;
3037 event.code = SYN_DROPPED;
3038 event.value = 0;
3039 unused = mDevice->process(&event, /*count=*/1);
3040 mapper.assertProcessWasNotCalled();
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003041
3042 // All events until the next SYN_REPORT should be dropped.
3043 event.type = EV_KEY;
3044 event.code = KEY_A;
3045 event.value = 1;
3046 unused = mDevice->process(&event, /*count=*/1);
3047 mapper.assertProcessWasNotCalled();
3048
3049 // We get the SYN_REPORT event now, which is not forwarded to mappers.
Arpit Singh4b4a4572023-11-24 18:19:56 +00003050 // This should reset the mapper.
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003051 event.type = EV_SYN;
3052 event.code = SYN_REPORT;
3053 event.value = 0;
3054 unused = mDevice->process(&event, /*count=*/1);
3055 mapper.assertProcessWasNotCalled();
Arpit Singh4b4a4572023-11-24 18:19:56 +00003056 mapper.assertResetWasCalled();
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003057
3058 // The mapper receives events normally now.
3059 event.type = EV_KEY;
3060 event.code = KEY_B;
3061 event.value = 1;
3062 unused = mDevice->process(&event, /*count=*/1);
3063 mapper.assertProcessWasCalled();
3064}
3065
Michael Wrightd02c5b62014-02-10 15:10:22 -08003066// --- SwitchInputMapperTest ---
3067
3068class SwitchInputMapperTest : public InputMapperTest {
3069protected:
3070};
3071
3072TEST_F(SwitchInputMapperTest, GetSources) {
Arpit Singhdf992eb2023-04-26 16:12:10 +00003073 SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08003074
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003075 ASSERT_EQ(uint32_t(AINPUT_SOURCE_SWITCH), mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003076}
3077
3078TEST_F(SwitchInputMapperTest, GetSwitchState) {
Arpit Singhdf992eb2023-04-26 16:12:10 +00003079 SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08003080
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003081 mFakeEventHub->setSwitchState(EVENTHUB_ID, SW_LID, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003082 ASSERT_EQ(1, mapper.getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003083
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003084 mFakeEventHub->setSwitchState(EVENTHUB_ID, SW_LID, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003085 ASSERT_EQ(0, mapper.getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003086}
3087
3088TEST_F(SwitchInputMapperTest, Process) {
Arpit Singhdf992eb2023-04-26 16:12:10 +00003089 SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003090 std::list<NotifyArgs> out;
3091 out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SW, SW_LID, 1);
3092 ASSERT_TRUE(out.empty());
3093 out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SW, SW_JACK_PHYSICAL_INSERT, 1);
3094 ASSERT_TRUE(out.empty());
3095 out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SW, SW_HEADPHONE_INSERT, 0);
3096 ASSERT_TRUE(out.empty());
3097 out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003098
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003099 ASSERT_EQ(1u, out.size());
3100 const NotifySwitchArgs& args = std::get<NotifySwitchArgs>(*out.begin());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003101 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
Dan Albert1bd2fc02016-02-02 15:11:57 -08003102 ASSERT_EQ((1U << SW_LID) | (1U << SW_JACK_PHYSICAL_INSERT), args.switchValues);
3103 ASSERT_EQ((1U << SW_LID) | (1U << SW_JACK_PHYSICAL_INSERT) | (1 << SW_HEADPHONE_INSERT),
Michael Wrightd02c5b62014-02-10 15:10:22 -08003104 args.switchMask);
3105 ASSERT_EQ(uint32_t(0), args.policyFlags);
3106}
3107
Chris Ye87143712020-11-10 05:05:58 +00003108// --- VibratorInputMapperTest ---
3109class VibratorInputMapperTest : public InputMapperTest {
3110protected:
3111 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::VIBRATOR); }
3112};
3113
3114TEST_F(VibratorInputMapperTest, GetSources) {
Arpit Singh0f26b302023-04-26 16:23:13 +00003115 VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
Chris Ye87143712020-11-10 05:05:58 +00003116
3117 ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mapper.getSources());
3118}
3119
3120TEST_F(VibratorInputMapperTest, GetVibratorIds) {
Arpit Singh0f26b302023-04-26 16:23:13 +00003121 VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
Chris Ye87143712020-11-10 05:05:58 +00003122
3123 ASSERT_EQ(mapper.getVibratorIds().size(), 2U);
3124}
3125
3126TEST_F(VibratorInputMapperTest, Vibrate) {
3127 constexpr uint8_t DEFAULT_AMPLITUDE = 192;
Chris Yefb552902021-02-03 17:18:37 -08003128 constexpr int32_t VIBRATION_TOKEN = 100;
Arpit Singh0f26b302023-04-26 16:23:13 +00003129 VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
Chris Ye87143712020-11-10 05:05:58 +00003130
3131 VibrationElement pattern(2);
3132 VibrationSequence sequence(2);
3133 pattern.duration = std::chrono::milliseconds(200);
Harry Cutts33476232023-01-30 19:57:29 +00003134 pattern.channels = {{/*vibratorId=*/0, DEFAULT_AMPLITUDE / 2},
3135 {/*vibratorId=*/1, DEFAULT_AMPLITUDE}};
Chris Ye87143712020-11-10 05:05:58 +00003136 sequence.addElement(pattern);
3137 pattern.duration = std::chrono::milliseconds(500);
Harry Cutts33476232023-01-30 19:57:29 +00003138 pattern.channels = {{/*vibratorId=*/0, DEFAULT_AMPLITUDE / 4},
3139 {/*vibratorId=*/1, DEFAULT_AMPLITUDE}};
Chris Ye87143712020-11-10 05:05:58 +00003140 sequence.addElement(pattern);
3141
3142 std::vector<int64_t> timings = {0, 1};
3143 std::vector<uint8_t> amplitudes = {DEFAULT_AMPLITUDE, DEFAULT_AMPLITUDE / 2};
3144
3145 ASSERT_FALSE(mapper.isVibrating());
Chris Yefb552902021-02-03 17:18:37 -08003146 // Start vibrating
Harry Cutts33476232023-01-30 19:57:29 +00003147 std::list<NotifyArgs> out = mapper.vibrate(sequence, /*repeat=*/-1, VIBRATION_TOKEN);
Chris Ye87143712020-11-10 05:05:58 +00003148 ASSERT_TRUE(mapper.isVibrating());
Chris Yefb552902021-02-03 17:18:37 -08003149 // Verify vibrator state listener was notified.
3150 mReader->loopOnce();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003151 ASSERT_EQ(1u, out.size());
3152 const NotifyVibratorStateArgs& vibrateArgs = std::get<NotifyVibratorStateArgs>(*out.begin());
3153 ASSERT_EQ(DEVICE_ID, vibrateArgs.deviceId);
3154 ASSERT_TRUE(vibrateArgs.isOn);
Chris Yefb552902021-02-03 17:18:37 -08003155 // Stop vibrating
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003156 out = mapper.cancelVibrate(VIBRATION_TOKEN);
Chris Yefb552902021-02-03 17:18:37 -08003157 ASSERT_FALSE(mapper.isVibrating());
3158 // Verify vibrator state listener was notified.
3159 mReader->loopOnce();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003160 ASSERT_EQ(1u, out.size());
3161 const NotifyVibratorStateArgs& cancelArgs = std::get<NotifyVibratorStateArgs>(*out.begin());
3162 ASSERT_EQ(DEVICE_ID, cancelArgs.deviceId);
3163 ASSERT_FALSE(cancelArgs.isOn);
Chris Ye87143712020-11-10 05:05:58 +00003164}
Michael Wrightd02c5b62014-02-10 15:10:22 -08003165
Chris Yef59a2f42020-10-16 12:55:26 -07003166// --- SensorInputMapperTest ---
3167
3168class SensorInputMapperTest : public InputMapperTest {
3169protected:
3170 static const int32_t ACCEL_RAW_MIN;
3171 static const int32_t ACCEL_RAW_MAX;
3172 static const int32_t ACCEL_RAW_FUZZ;
3173 static const int32_t ACCEL_RAW_FLAT;
3174 static const int32_t ACCEL_RAW_RESOLUTION;
3175
3176 static const int32_t GYRO_RAW_MIN;
3177 static const int32_t GYRO_RAW_MAX;
3178 static const int32_t GYRO_RAW_FUZZ;
3179 static const int32_t GYRO_RAW_FLAT;
3180 static const int32_t GYRO_RAW_RESOLUTION;
3181
3182 static const float GRAVITY_MS2_UNIT;
3183 static const float DEGREE_RADIAN_UNIT;
3184
3185 void prepareAccelAxes();
3186 void prepareGyroAxes();
3187 void setAccelProperties();
3188 void setGyroProperties();
3189 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::SENSOR); }
3190};
3191
3192const int32_t SensorInputMapperTest::ACCEL_RAW_MIN = -32768;
3193const int32_t SensorInputMapperTest::ACCEL_RAW_MAX = 32768;
3194const int32_t SensorInputMapperTest::ACCEL_RAW_FUZZ = 16;
3195const int32_t SensorInputMapperTest::ACCEL_RAW_FLAT = 0;
3196const int32_t SensorInputMapperTest::ACCEL_RAW_RESOLUTION = 8192;
3197
3198const int32_t SensorInputMapperTest::GYRO_RAW_MIN = -2097152;
3199const int32_t SensorInputMapperTest::GYRO_RAW_MAX = 2097152;
3200const int32_t SensorInputMapperTest::GYRO_RAW_FUZZ = 16;
3201const int32_t SensorInputMapperTest::GYRO_RAW_FLAT = 0;
3202const int32_t SensorInputMapperTest::GYRO_RAW_RESOLUTION = 1024;
3203
3204const float SensorInputMapperTest::GRAVITY_MS2_UNIT = 9.80665f;
3205const float SensorInputMapperTest::DEGREE_RADIAN_UNIT = 0.0174533f;
3206
3207void SensorInputMapperTest::prepareAccelAxes() {
3208 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3209 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3210 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3211 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3212 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Z, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3213 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3214}
3215
3216void SensorInputMapperTest::prepareGyroAxes() {
3217 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RX, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3218 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3219 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RY, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3220 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3221 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RZ, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3222 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3223}
3224
3225void SensorInputMapperTest::setAccelProperties() {
3226 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 0, InputDeviceSensorType::ACCELEROMETER,
3227 /* sensorDataIndex */ 0);
3228 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 1, InputDeviceSensorType::ACCELEROMETER,
3229 /* sensorDataIndex */ 1);
3230 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 2, InputDeviceSensorType::ACCELEROMETER,
3231 /* sensorDataIndex */ 2);
3232 mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP);
3233 addConfigurationProperty("sensor.accelerometer.reportingMode", "0");
3234 addConfigurationProperty("sensor.accelerometer.maxDelay", "100000");
3235 addConfigurationProperty("sensor.accelerometer.minDelay", "5000");
3236 addConfigurationProperty("sensor.accelerometer.power", "1.5");
3237}
3238
3239void SensorInputMapperTest::setGyroProperties() {
3240 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 3, InputDeviceSensorType::GYROSCOPE,
3241 /* sensorDataIndex */ 0);
3242 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 4, InputDeviceSensorType::GYROSCOPE,
3243 /* sensorDataIndex */ 1);
3244 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 5, InputDeviceSensorType::GYROSCOPE,
3245 /* sensorDataIndex */ 2);
3246 mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP);
3247 addConfigurationProperty("sensor.gyroscope.reportingMode", "0");
3248 addConfigurationProperty("sensor.gyroscope.maxDelay", "100000");
3249 addConfigurationProperty("sensor.gyroscope.minDelay", "5000");
3250 addConfigurationProperty("sensor.gyroscope.power", "0.8");
3251}
3252
3253TEST_F(SensorInputMapperTest, GetSources) {
Arpit Singhfb706c32023-04-26 15:07:55 +00003254 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003255
3256 ASSERT_EQ(static_cast<uint32_t>(AINPUT_SOURCE_SENSOR), mapper.getSources());
3257}
3258
3259TEST_F(SensorInputMapperTest, ProcessAccelerometerSensor) {
3260 setAccelProperties();
3261 prepareAccelAxes();
Arpit Singhfb706c32023-04-26 15:07:55 +00003262 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003263
3264 ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::ACCELEROMETER,
3265 std::chrono::microseconds(10000),
3266 std::chrono::microseconds(0)));
Chris Yee14523a2020-12-19 13:46:00 -08003267 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003268 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, 20000);
3269 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, -20000);
3270 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Z, 40000);
3271 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000);
3272 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Chris Yef59a2f42020-10-16 12:55:26 -07003273
3274 NotifySensorArgs args;
3275 std::vector<float> values = {20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT,
3276 -20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT,
3277 40000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT};
3278
3279 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args));
3280 ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR);
3281 ASSERT_EQ(args.deviceId, DEVICE_ID);
3282 ASSERT_EQ(args.sensorType, InputDeviceSensorType::ACCELEROMETER);
3283 ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH);
3284 ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME);
3285 ASSERT_EQ(args.values, values);
3286 mapper.flushSensor(InputDeviceSensorType::ACCELEROMETER);
3287}
3288
3289TEST_F(SensorInputMapperTest, ProcessGyroscopeSensor) {
3290 setGyroProperties();
3291 prepareGyroAxes();
Arpit Singhfb706c32023-04-26 15:07:55 +00003292 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003293
3294 ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::GYROSCOPE,
3295 std::chrono::microseconds(10000),
3296 std::chrono::microseconds(0)));
Chris Yee14523a2020-12-19 13:46:00 -08003297 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003298 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RX, 20000);
3299 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RY, -20000);
3300 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RZ, 40000);
3301 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000);
3302 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Chris Yef59a2f42020-10-16 12:55:26 -07003303
3304 NotifySensorArgs args;
3305 std::vector<float> values = {20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT,
3306 -20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT,
3307 40000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT};
3308
3309 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args));
3310 ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR);
3311 ASSERT_EQ(args.deviceId, DEVICE_ID);
3312 ASSERT_EQ(args.sensorType, InputDeviceSensorType::GYROSCOPE);
3313 ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH);
3314 ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME);
3315 ASSERT_EQ(args.values, values);
3316 mapper.flushSensor(InputDeviceSensorType::GYROSCOPE);
3317}
3318
Michael Wrightd02c5b62014-02-10 15:10:22 -08003319// --- KeyboardInputMapperTest ---
3320
3321class KeyboardInputMapperTest : public InputMapperTest {
3322protected:
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003323 void SetUp() override {
3324 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
3325 InputDeviceClass::ALPHAKEY);
3326 }
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003327 const std::string UNIQUE_ID = "local:0";
Zixuan Qufecb6062022-11-12 04:44:31 +00003328 const KeyboardLayoutInfo DEVICE_KEYBOARD_LAYOUT_INFO = KeyboardLayoutInfo("en-US", "qwerty");
Michael Wrighta9cf4192022-12-01 23:46:39 +00003329 void prepareDisplay(ui::Rotation orientation);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003330
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003331 void testDPadKeyRotation(KeyboardInputMapper& mapper, int32_t originalScanCode,
Arthur Hung2c9a3342019-07-23 14:18:59 +08003332 int32_t originalKeyCode, int32_t rotatedKeyCode,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003333 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003334};
3335
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003336/* Similar to setDisplayInfoAndReconfigure, but pre-populates all parameters except for the
3337 * orientation.
3338 */
Michael Wrighta9cf4192022-12-01 23:46:39 +00003339void KeyboardInputMapperTest::prepareDisplay(ui::Rotation orientation) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003340 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
3341 NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003342}
3343
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003344void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper& mapper,
Arthur Hung2c9a3342019-07-23 14:18:59 +08003345 int32_t originalScanCode, int32_t originalKeyCode,
Linnan Li13bf76a2024-05-05 19:18:02 +08003346 int32_t rotatedKeyCode,
3347 ui::LogicalDisplayId displayId) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003348 NotifyKeyArgs args;
3349
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003350 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003351 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3352 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3353 ASSERT_EQ(originalScanCode, args.scanCode);
3354 ASSERT_EQ(rotatedKeyCode, args.keyCode);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003355 ASSERT_EQ(displayId, args.displayId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003356
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003357 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003358 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3359 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3360 ASSERT_EQ(originalScanCode, args.scanCode);
3361 ASSERT_EQ(rotatedKeyCode, args.keyCode);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003362 ASSERT_EQ(displayId, args.displayId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003363}
3364
Michael Wrightd02c5b62014-02-10 15:10:22 -08003365TEST_F(KeyboardInputMapperTest, GetSources) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003366 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003367 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003368
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003369 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003370}
3371
3372TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) {
3373 const int32_t USAGE_A = 0x070004;
3374 const int32_t USAGE_UNKNOWN = 0x07ffff;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003375 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3376 mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
Chris Yea52ade12020-08-27 16:49:20 -07003377 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, POLICY_FLAG_WAKE);
3378 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, POLICY_FLAG_WAKE);
3379 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, POLICY_FLAG_WAKE);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003380
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003381 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003382 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003383 // Initial metastate is AMETA_NONE.
3384 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003385
3386 // Key down by scan code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003387 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003388 NotifyKeyArgs args;
3389 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3390 ASSERT_EQ(DEVICE_ID, args.deviceId);
3391 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3392 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3393 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3394 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3395 ASSERT_EQ(KEY_HOME, args.scanCode);
3396 ASSERT_EQ(AMETA_NONE, args.metaState);
3397 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3398 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3399 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3400
3401 // Key up by scan code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003402 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003403 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3404 ASSERT_EQ(DEVICE_ID, args.deviceId);
3405 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3406 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3407 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3408 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3409 ASSERT_EQ(KEY_HOME, args.scanCode);
3410 ASSERT_EQ(AMETA_NONE, args.metaState);
3411 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3412 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3413 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3414
3415 // Key down by usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003416 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A);
3417 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, 0, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003418 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3419 ASSERT_EQ(DEVICE_ID, args.deviceId);
3420 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3421 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3422 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3423 ASSERT_EQ(AKEYCODE_A, args.keyCode);
3424 ASSERT_EQ(0, args.scanCode);
3425 ASSERT_EQ(AMETA_NONE, args.metaState);
3426 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3427 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3428 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3429
3430 // Key up by usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003431 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A);
3432 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003433 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3434 ASSERT_EQ(DEVICE_ID, args.deviceId);
3435 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3436 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3437 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3438 ASSERT_EQ(AKEYCODE_A, args.keyCode);
3439 ASSERT_EQ(0, args.scanCode);
3440 ASSERT_EQ(AMETA_NONE, args.metaState);
3441 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3442 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3443 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3444
3445 // Key down with unknown scan code or usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003446 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
3447 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003448 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3449 ASSERT_EQ(DEVICE_ID, args.deviceId);
3450 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3451 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3452 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3453 ASSERT_EQ(0, args.keyCode);
3454 ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
3455 ASSERT_EQ(AMETA_NONE, args.metaState);
3456 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3457 ASSERT_EQ(0U, args.policyFlags);
3458 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3459
3460 // Key up with unknown scan code or usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003461 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
3462 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_UNKNOWN, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003463 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3464 ASSERT_EQ(DEVICE_ID, args.deviceId);
3465 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3466 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3467 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3468 ASSERT_EQ(0, args.keyCode);
3469 ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
3470 ASSERT_EQ(AMETA_NONE, args.metaState);
3471 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3472 ASSERT_EQ(0U, args.policyFlags);
3473 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3474}
3475
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003476TEST_F(KeyboardInputMapperTest, Process_KeyRemapping) {
3477 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
3478 mFakeEventHub->addKey(EVENTHUB_ID, KEY_B, 0, AKEYCODE_B, 0);
3479 mFakeEventHub->addKeyRemapping(EVENTHUB_ID, AKEYCODE_A, AKEYCODE_B);
3480
3481 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003482 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003483
3484 // Key down by scan code.
3485 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_A, 1);
3486 NotifyKeyArgs args;
3487 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3488 ASSERT_EQ(AKEYCODE_B, args.keyCode);
3489
3490 // Key up by scan code.
3491 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 0);
3492 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3493 ASSERT_EQ(AKEYCODE_B, args.keyCode);
3494}
3495
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003496/**
3497 * Ensure that the readTime is set to the time when the EV_KEY is received.
3498 */
3499TEST_F(KeyboardInputMapperTest, Process_SendsReadTime) {
3500 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3501
3502 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003503 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003504 NotifyKeyArgs args;
3505
3506 // Key down
Harry Cutts33476232023-01-30 19:57:29 +00003507 process(mapper, ARBITRARY_TIME, /*readTime=*/12, EV_KEY, KEY_HOME, 1);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003508 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3509 ASSERT_EQ(12, args.readTime);
3510
3511 // Key up
Harry Cutts33476232023-01-30 19:57:29 +00003512 process(mapper, ARBITRARY_TIME, /*readTime=*/15, EV_KEY, KEY_HOME, 1);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003513 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3514 ASSERT_EQ(15, args.readTime);
3515}
3516
Michael Wrightd02c5b62014-02-10 15:10:22 -08003517TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003518 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFTSHIFT, 0, AKEYCODE_SHIFT_LEFT, 0);
3519 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
Chris Yea52ade12020-08-27 16:49:20 -07003520 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 0);
3521 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0);
3522 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003523
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003524 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003525 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003526
Arthur Hung95f68612022-04-07 14:08:22 +08003527 // Initial metastate is AMETA_NONE.
3528 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003529
3530 // Metakey down.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003531 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003532 NotifyKeyArgs args;
3533 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3534 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003535 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
arthurhungdcef2dc2020-08-11 14:47:50 +08003536 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003537
3538 // Key down.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003539 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003540 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3541 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003542 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003543
3544 // Key up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003545 process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_KEY, KEY_A, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003546 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3547 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003548 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003549
3550 // Metakey up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003551 process(mapper, ARBITRARY_TIME + 3, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003552 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3553 ASSERT_EQ(AMETA_NONE, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003554 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
arthurhungdcef2dc2020-08-11 14:47:50 +08003555 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003556}
3557
3558TEST_F(KeyboardInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateDPad) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003559 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3560 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3561 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3562 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003563
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003564 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003565 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003566
Michael Wrighta9cf4192022-12-01 23:46:39 +00003567 prepareDisplay(ui::ROTATION_90);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003568 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3569 KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
3570 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3571 KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
3572 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3573 KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
3574 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3575 KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
3576}
3577
3578TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003579 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3580 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3581 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3582 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003583
Michael Wrightd02c5b62014-02-10 15:10:22 -08003584 addConfigurationProperty("keyboard.orientationAware", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003585 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003586 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003587
Michael Wrighta9cf4192022-12-01 23:46:39 +00003588 prepareDisplay(ui::ROTATION_0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003589 ASSERT_NO_FATAL_FAILURE(
3590 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
3591 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3592 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3593 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3594 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3595 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3596 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003597
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003598 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003599 prepareDisplay(ui::ROTATION_90);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003600 ASSERT_NO_FATAL_FAILURE(
3601 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3602 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3603 AKEYCODE_DPAD_UP, DISPLAY_ID));
3604 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3605 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3606 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3607 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003608
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003609 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003610 prepareDisplay(ui::ROTATION_180);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003611 ASSERT_NO_FATAL_FAILURE(
3612 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3613 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3614 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3615 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3616 AKEYCODE_DPAD_UP, DISPLAY_ID));
3617 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3618 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003619
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003620 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003621 prepareDisplay(ui::ROTATION_270);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003622 ASSERT_NO_FATAL_FAILURE(
3623 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3624 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3625 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3626 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3627 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3628 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3629 AKEYCODE_DPAD_UP, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003630
3631 // Special case: if orientation changes while key is down, we still emit the same keycode
3632 // in the key up as we did in the key down.
3633 NotifyKeyArgs args;
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003634 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003635 prepareDisplay(ui::ROTATION_270);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003636 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003637 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3638 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3639 ASSERT_EQ(KEY_UP, args.scanCode);
3640 ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
3641
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003642 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003643 prepareDisplay(ui::ROTATION_180);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003644 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003645 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3646 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3647 ASSERT_EQ(KEY_UP, args.scanCode);
3648 ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
3649}
3650
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003651TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_NotOrientationAware) {
3652 // If the keyboard is not orientation aware,
3653 // key events should not be associated with a specific display id
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003654 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003655
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003656 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003657 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003658 NotifyKeyArgs args;
3659
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003660 // Display id should be LogicalDisplayId::INVALID without any display configuration.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003661 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003662 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003663 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003664 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003665 ASSERT_EQ(ui::LogicalDisplayId::INVALID, args.displayId);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003666
Michael Wrighta9cf4192022-12-01 23:46:39 +00003667 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003668 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003669 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003670 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003671 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003672 ASSERT_EQ(ui::LogicalDisplayId::INVALID, args.displayId);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003673}
3674
3675TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_OrientationAware) {
3676 // If the keyboard is orientation aware,
3677 // key events should be associated with the internal viewport
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003678 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003679
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003680 addConfigurationProperty("keyboard.orientationAware", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003681 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003682 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003683 NotifyKeyArgs args;
3684
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003685 // Display id should be LogicalDisplayId::INVALID without any display configuration.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003686 // ^--- already checked by the previous test
3687
Michael Wrighta9cf4192022-12-01 23:46:39 +00003688 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003689 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003690 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003691 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003692 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003693 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3694 ASSERT_EQ(DISPLAY_ID, args.displayId);
3695
Linnan Li13bf76a2024-05-05 19:18:02 +08003696 constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003697 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003698 setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003699 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003700 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003701 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003702 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003703 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3704 ASSERT_EQ(newDisplayId, args.displayId);
3705}
3706
Michael Wrightd02c5b62014-02-10 15:10:22 -08003707TEST_F(KeyboardInputMapperTest, GetKeyCodeState) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003708 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003709 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003710
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003711 mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003712 ASSERT_EQ(1, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003713
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003714 mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003715 ASSERT_EQ(0, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003716}
3717
Philip Junker4af3b3d2021-12-14 10:36:55 +01003718TEST_F(KeyboardInputMapperTest, GetKeyCodeForKeyLocation) {
3719 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003720 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Philip Junker4af3b3d2021-12-14 10:36:55 +01003721
3722 mFakeEventHub->addKeyCodeMapping(EVENTHUB_ID, AKEYCODE_Y, AKEYCODE_Z);
3723 ASSERT_EQ(AKEYCODE_Z, mapper.getKeyCodeForKeyLocation(AKEYCODE_Y))
3724 << "If a mapping is available, the result is equal to the mapping";
3725
3726 ASSERT_EQ(AKEYCODE_A, mapper.getKeyCodeForKeyLocation(AKEYCODE_A))
3727 << "If no mapping is available, the result is the key location";
3728}
3729
Michael Wrightd02c5b62014-02-10 15:10:22 -08003730TEST_F(KeyboardInputMapperTest, GetScanCodeState) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003731 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003732 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003733
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003734 mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003735 ASSERT_EQ(1, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003736
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003737 mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003738 ASSERT_EQ(0, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003739}
3740
3741TEST_F(KeyboardInputMapperTest, MarkSupportedKeyCodes) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003742 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003743 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003744
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003745 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003746
Michael Wrightd02c5b62014-02-10 15:10:22 -08003747 uint8_t flags[2] = { 0, 0 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07003748 ASSERT_TRUE(mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_A, AKEYCODE_B}, flags));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003749 ASSERT_TRUE(flags[0]);
3750 ASSERT_FALSE(flags[1]);
3751}
3752
3753TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003754 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3755 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3756 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3757 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3758 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3759 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003760
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003761 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003762 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003763 // Initial metastate is AMETA_NONE.
3764 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003765
3766 // Initialization should have turned all of the lights off.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003767 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3768 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3769 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003770
3771 // Toggle caps lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003772 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3773 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003774 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3775 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3776 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003777 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003778
3779 // Toggle num lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003780 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3781 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003782 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3783 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3784 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003785 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003786
3787 // Toggle caps lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003788 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3789 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003790 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3791 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3792 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003793 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003794
3795 // Toggle scroll lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003796 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3797 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003798 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3799 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3800 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003801 ASSERT_EQ(AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003802
3803 // Toggle num lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003804 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3805 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003806 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3807 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3808 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003809 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003810
3811 // Toggle scroll lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003812 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3813 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003814 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3815 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3816 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003817 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003818}
3819
Chris Yea52ade12020-08-27 16:49:20 -07003820TEST_F(KeyboardInputMapperTest, NoMetaStateWhenMetaKeysNotPresent) {
3821 mFakeEventHub->addKey(EVENTHUB_ID, BTN_A, 0, AKEYCODE_BUTTON_A, 0);
3822 mFakeEventHub->addKey(EVENTHUB_ID, BTN_B, 0, AKEYCODE_BUTTON_B, 0);
3823 mFakeEventHub->addKey(EVENTHUB_ID, BTN_X, 0, AKEYCODE_BUTTON_X, 0);
3824 mFakeEventHub->addKey(EVENTHUB_ID, BTN_Y, 0, AKEYCODE_BUTTON_Y, 0);
3825
3826 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003827 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Chris Yea52ade12020-08-27 16:49:20 -07003828
Chris Yea52ade12020-08-27 16:49:20 -07003829 // Meta state should be AMETA_NONE after reset
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003830 std::list<NotifyArgs> unused = mapper.reset(ARBITRARY_TIME);
Chris Yea52ade12020-08-27 16:49:20 -07003831 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3832 // Meta state should be AMETA_NONE with update, as device doesn't have the keys.
3833 mapper.updateMetaState(AKEYCODE_NUM_LOCK);
3834 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3835
3836 NotifyKeyArgs args;
3837 // Press button "A"
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003838 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_A, 1);
Chris Yea52ade12020-08-27 16:49:20 -07003839 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3840 ASSERT_EQ(AMETA_NONE, args.metaState);
3841 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3842 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3843 ASSERT_EQ(AKEYCODE_BUTTON_A, args.keyCode);
3844
3845 // Button up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003846 process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_KEY, BTN_A, 0);
Chris Yea52ade12020-08-27 16:49:20 -07003847 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3848 ASSERT_EQ(AMETA_NONE, args.metaState);
3849 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3850 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3851 ASSERT_EQ(AKEYCODE_BUTTON_A, args.keyCode);
3852}
3853
Arthur Hung2c9a3342019-07-23 14:18:59 +08003854TEST_F(KeyboardInputMapperTest, Configure_AssignsDisplayPort) {
3855 // keyboard 1.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003856 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3857 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3858 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3859 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003860
3861 // keyboard 2.
3862 const std::string USB2 = "USB2";
arthurhungdcef2dc2020-08-11 14:47:50 +08003863 const std::string DEVICE_NAME2 = "KEYBOARD2";
Arthur Hung2c9a3342019-07-23 14:18:59 +08003864 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003865 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
arthurhungdcef2dc2020-08-11 14:47:50 +08003866 std::shared_ptr<InputDevice> device2 =
3867 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
Dominik Laskowski2f01d772022-03-23 16:01:29 -07003868 ftl::Flags<InputDeviceClass>(0));
arthurhungdcef2dc2020-08-11 14:47:50 +08003869
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003870 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3871 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3872 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3873 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003874
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003875 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003876 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003877
Arpit Singh67ca6842023-04-26 14:43:16 +00003878 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003879 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003880 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3881 mFakePolicy
3882 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003883 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003884 std::list<NotifyArgs> unused =
3885 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003886 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003887 unused += device2->reset(ARBITRARY_TIME);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003888
3889 // Prepared displays and associated info.
3890 constexpr uint8_t hdmi1 = 0;
3891 constexpr uint8_t hdmi2 = 1;
3892 const std::string SECONDARY_UNIQUE_ID = "local:1";
3893
3894 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
3895 mFakePolicy->addInputPortAssociation(USB2, hdmi2);
3896
3897 // No associated display viewport found, should disable the device.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003898 unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003899 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003900 ASSERT_FALSE(device2->isEnabled());
3901
3902 // Prepare second display.
Linnan Li13bf76a2024-05-05 19:18:02 +08003903 constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
Michael Wrighta9cf4192022-12-01 23:46:39 +00003904 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003905 UNIQUE_ID, hdmi1, ViewportType::INTERNAL);
Michael Wrighta9cf4192022-12-01 23:46:39 +00003906 setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003907 SECONDARY_UNIQUE_ID, hdmi2, ViewportType::EXTERNAL);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003908 // Default device will reconfigure above, need additional reconfiguration for another device.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003909 unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003910 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003911
3912 // Device should be enabled after the associated display is found.
3913 ASSERT_TRUE(mDevice->isEnabled());
3914 ASSERT_TRUE(device2->isEnabled());
3915
3916 // Test pad key events
3917 ASSERT_NO_FATAL_FAILURE(
3918 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
3919 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3920 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3921 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3922 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3923 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3924 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3925
3926 ASSERT_NO_FATAL_FAILURE(
3927 testDPadKeyRotation(mapper2, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, newDisplayId));
3928 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3929 AKEYCODE_DPAD_RIGHT, newDisplayId));
3930 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3931 AKEYCODE_DPAD_DOWN, newDisplayId));
3932 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3933 AKEYCODE_DPAD_LEFT, newDisplayId));
3934}
Michael Wrightd02c5b62014-02-10 15:10:22 -08003935
arthurhungc903df12020-08-11 15:08:42 +08003936TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleAfterReattach) {
3937 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3938 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3939 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3940 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3941 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3942 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3943
3944 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003945 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003946 // Initial metastate is AMETA_NONE.
3947 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
arthurhungc903df12020-08-11 15:08:42 +08003948
3949 // Initialization should have turned all of the lights off.
3950 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3951 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3952 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3953
3954 // Toggle caps lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003955 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3956 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003957 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3958 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
3959
3960 // Toggle num lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003961 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3962 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003963 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3964 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
3965
3966 // Toggle scroll lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003967 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3968 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003969 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3970 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
3971
3972 mFakeEventHub->removeDevice(EVENTHUB_ID);
3973 mReader->loopOnce();
3974
3975 // keyboard 2 should default toggle keys.
3976 const std::string USB2 = "USB2";
3977 const std::string DEVICE_NAME2 = "KEYBOARD2";
3978 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
3979 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
3980 std::shared_ptr<InputDevice> device2 =
3981 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
Dominik Laskowski2f01d772022-03-23 16:01:29 -07003982 ftl::Flags<InputDeviceClass>(0));
arthurhungc903df12020-08-11 15:08:42 +08003983 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3984 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
3985 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3986 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3987 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3988 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3989
Arpit Singh67ca6842023-04-26 14:43:16 +00003990 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
arthurhung6fe95782020-10-05 22:41:16 +08003991 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003992 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3993 mFakePolicy
3994 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003995 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003996 std::list<NotifyArgs> unused =
3997 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003998 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003999 unused += device2->reset(ARBITRARY_TIME);
arthurhungc903df12020-08-11 15:08:42 +08004000
4001 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_CAPSL));
4002 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_NUML));
4003 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_SCROLLL));
arthurhung6fe95782020-10-05 22:41:16 +08004004 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON,
4005 mapper2.getMetaState());
arthurhungc903df12020-08-11 15:08:42 +08004006}
4007
Arthur Hungcb40a002021-08-03 14:31:01 +00004008TEST_F(KeyboardInputMapperTest, Process_toggleCapsLockState) {
4009 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
4010 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
4011 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
4012
4013 // Suppose we have two mappers. (DPAD + KEYBOARD)
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004014 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD);
Arthur Hungcb40a002021-08-03 14:31:01 +00004015 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004016 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08004017 // Initial metastate is AMETA_NONE.
4018 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Arthur Hungcb40a002021-08-03 14:31:01 +00004019
4020 mReader->toggleCapsLockState(DEVICE_ID);
4021 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
4022}
4023
Arthur Hungfb3cc112022-04-13 07:39:50 +00004024TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleInMultiDevices) {
4025 // keyboard 1.
4026 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
4027 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
4028 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
4029 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
4030 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
4031 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
4032
4033 KeyboardInputMapper& mapper1 =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004034 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hungfb3cc112022-04-13 07:39:50 +00004035
4036 // keyboard 2.
4037 const std::string USB2 = "USB2";
4038 const std::string DEVICE_NAME2 = "KEYBOARD2";
4039 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
4040 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
4041 std::shared_ptr<InputDevice> device2 =
4042 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
4043 ftl::Flags<InputDeviceClass>(0));
4044 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
4045 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
4046 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
4047 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
4048 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
4049 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
4050
Arpit Singh67ca6842023-04-26 14:43:16 +00004051 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
Arthur Hungfb3cc112022-04-13 07:39:50 +00004052 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00004053 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
4054 mFakePolicy
4055 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004056 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07004057 std::list<NotifyArgs> unused =
4058 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004059 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07004060 unused += device2->reset(ARBITRARY_TIME);
Arthur Hungfb3cc112022-04-13 07:39:50 +00004061
Arthur Hung95f68612022-04-07 14:08:22 +08004062 // Initial metastate is AMETA_NONE.
4063 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
4064 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
4065
4066 // Toggle num lock on and off.
4067 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
4068 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Arthur Hungfb3cc112022-04-13 07:39:50 +00004069 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
4070 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper1.getMetaState());
4071 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper2.getMetaState());
4072
4073 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
4074 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
4075 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
4076 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
4077 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
4078
4079 // Toggle caps lock on and off.
4080 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
4081 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
4082 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
4083 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper1.getMetaState());
4084 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper2.getMetaState());
4085
4086 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
4087 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
4088 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
4089 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
4090 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
4091
4092 // Toggle scroll lock on and off.
4093 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
4094 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
4095 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
4096 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper1.getMetaState());
4097 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper2.getMetaState());
4098
4099 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
4100 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
4101 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
4102 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
4103 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
4104}
4105
Arthur Hung2141d542022-08-23 07:45:21 +00004106TEST_F(KeyboardInputMapperTest, Process_DisabledDevice) {
4107 const int32_t USAGE_A = 0x070004;
4108 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4109 mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
4110
4111 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004112 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung2141d542022-08-23 07:45:21 +00004113 // Key down by scan code.
4114 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
4115 NotifyKeyArgs args;
4116 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4117 ASSERT_EQ(DEVICE_ID, args.deviceId);
4118 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4119 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4120 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
4121 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4122 ASSERT_EQ(KEY_HOME, args.scanCode);
4123 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
4124
4125 // Disable device, it should synthesize cancellation events for down events.
4126 mFakePolicy->addDisabledDevice(DEVICE_ID);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004127 configureDevice(InputReaderConfiguration::Change::ENABLED_STATE);
Arthur Hung2141d542022-08-23 07:45:21 +00004128
4129 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4130 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
4131 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4132 ASSERT_EQ(KEY_HOME, args.scanCode);
4133 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_CANCELED, args.flags);
4134}
4135
Zixuan Qufecb6062022-11-12 04:44:31 +00004136TEST_F(KeyboardInputMapperTest, Configure_AssignKeyboardLayoutInfo) {
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004137 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Zixuan Qufecb6062022-11-12 04:44:31 +00004138 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004139 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
4140 /*changes=*/{});
Zixuan Qufecb6062022-11-12 04:44:31 +00004141
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +00004142 uint32_t generation = mReader->getContext()->getGeneration();
Zixuan Qufecb6062022-11-12 04:44:31 +00004143 mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
4144
4145 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004146 InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
Zixuan Qufecb6062022-11-12 04:44:31 +00004147
4148 InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
4149 ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.languageTag,
4150 deviceInfo.getKeyboardLayoutInfo()->languageTag);
4151 ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.layoutType,
4152 deviceInfo.getKeyboardLayoutInfo()->layoutType);
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +00004153 ASSERT_TRUE(mReader->getContext()->getGeneration() != generation);
4154
4155 // Call change layout association with the same values: Generation shouldn't change
4156 generation = mReader->getContext()->getGeneration();
4157 mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
4158 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
4159 InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
4160 ASSERT_TRUE(mReader->getContext()->getGeneration() == generation);
Zixuan Qufecb6062022-11-12 04:44:31 +00004161}
4162
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004163TEST_F(KeyboardInputMapperTest, LayoutInfoCorrectlyMapped) {
4164 mFakeEventHub->setRawLayoutInfo(EVENTHUB_ID,
4165 RawLayoutInfo{.languageTag = "en", .layoutType = "extended"});
4166
4167 // Configuration
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004168 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004169 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004170 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004171
4172 ASSERT_EQ("en", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->languageTag);
4173 ASSERT_EQ("extended", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->layoutType);
4174}
4175
Justin Chung71ddb432023-03-27 04:29:07 +00004176TEST_F(KeyboardInputMapperTest, Process_GesureEventToSetFlagKeepTouchMode) {
4177 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, POLICY_FLAG_GESTURE);
4178 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004179 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Justin Chung71ddb432023-03-27 04:29:07 +00004180 NotifyKeyArgs args;
4181
4182 // Key down
4183 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFT, 1);
4184 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4185 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_KEEP_TOUCH_MODE, args.flags);
4186}
4187
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004188// --- KeyboardInputMapperTest_ExternalAlphabeticDevice ---
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004189
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004190class KeyboardInputMapperTest_ExternalAlphabeticDevice : public InputMapperTest {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004191protected:
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004192 void SetUp() override {
4193 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
4194 InputDeviceClass::ALPHAKEY | InputDeviceClass::EXTERNAL);
4195 }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004196};
4197
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004198// --- KeyboardInputMapperTest_ExternalNonAlphabeticDevice ---
4199
4200class KeyboardInputMapperTest_ExternalNonAlphabeticDevice : public InputMapperTest {
4201protected:
4202 void SetUp() override {
4203 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
4204 InputDeviceClass::EXTERNAL);
4205 }
4206};
4207
4208TEST_F(KeyboardInputMapperTest_ExternalAlphabeticDevice, WakeBehavior_AlphabeticKeyboard) {
Vaibhav Devmurari16257862023-03-06 10:06:32 +00004209 // For external devices, keys will trigger wake on key down. Media keys should also trigger
4210 // wake if triggered from external devices.
Powei Fengd041c5d2019-05-03 17:11:33 -07004211
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004212 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, 0);
4213 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
4214 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
4215 POLICY_FLAG_WAKE);
Powei Fengd041c5d2019-05-03 17:11:33 -07004216
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004217 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004218 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Powei Fengd041c5d2019-05-03 17:11:33 -07004219
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004220 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004221 NotifyKeyArgs args;
4222 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4223 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4224
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004225 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004226 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4227 ASSERT_EQ(uint32_t(0), args.policyFlags);
4228
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004229 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004230 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Vaibhav Devmurari16257862023-03-06 10:06:32 +00004231 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
Powei Fengd041c5d2019-05-03 17:11:33 -07004232
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004233 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004234 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4235 ASSERT_EQ(uint32_t(0), args.policyFlags);
4236
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004237 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004238 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4239 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4240
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004241 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004242 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4243 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4244}
4245
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004246TEST_F(KeyboardInputMapperTest_ExternalNonAlphabeticDevice, WakeBehavior_NonAlphabeticKeyboard) {
Vaibhav Devmurari2681a812024-01-11 00:15:35 +00004247 // For external devices, keys will trigger wake on key down. Media keys should not trigger
4248 // wake if triggered from external non-alphaebtic keyboard (e.g. headsets).
4249
4250 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
4251 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
4252 POLICY_FLAG_WAKE);
4253
4254 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004255 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmurari2681a812024-01-11 00:15:35 +00004256
4257 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
4258 NotifyKeyArgs args;
4259 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4260 ASSERT_EQ(uint32_t(0), args.policyFlags);
4261
4262 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
4263 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4264 ASSERT_EQ(uint32_t(0), args.policyFlags);
4265
4266 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1);
4267 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4268 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4269
4270 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0);
4271 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4272 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4273}
4274
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004275TEST_F(KeyboardInputMapperTest_ExternalAlphabeticDevice, DoNotWakeByDefaultBehavior) {
Powei Fengd041c5d2019-05-03 17:11:33 -07004276 // Tv Remote key's wake behavior is prescribed by the keylayout file.
Powei Fengd041c5d2019-05-03 17:11:33 -07004277
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004278 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4279 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
4280 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, POLICY_FLAG_WAKE);
Powei Fengd041c5d2019-05-03 17:11:33 -07004281
Powei Fengd041c5d2019-05-03 17:11:33 -07004282 addConfigurationProperty("keyboard.doNotWakeByDefault", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004283 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004284 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Powei Fengd041c5d2019-05-03 17:11:33 -07004285
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004286 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004287 NotifyKeyArgs args;
4288 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4289 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4290
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004291 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004292 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4293 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4294
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004295 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_DOWN, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004296 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4297 ASSERT_EQ(uint32_t(0), args.policyFlags);
4298
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004299 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_DOWN, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004300 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4301 ASSERT_EQ(uint32_t(0), args.policyFlags);
4302
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004303 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004304 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4305 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4306
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004307 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004308 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4309 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4310}
4311
Michael Wrightd02c5b62014-02-10 15:10:22 -08004312// --- TouchInputMapperTest ---
4313
4314class TouchInputMapperTest : public InputMapperTest {
4315protected:
4316 static const int32_t RAW_X_MIN;
4317 static const int32_t RAW_X_MAX;
4318 static const int32_t RAW_Y_MIN;
4319 static const int32_t RAW_Y_MAX;
4320 static const int32_t RAW_TOUCH_MIN;
4321 static const int32_t RAW_TOUCH_MAX;
4322 static const int32_t RAW_TOOL_MIN;
4323 static const int32_t RAW_TOOL_MAX;
4324 static const int32_t RAW_PRESSURE_MIN;
4325 static const int32_t RAW_PRESSURE_MAX;
4326 static const int32_t RAW_ORIENTATION_MIN;
4327 static const int32_t RAW_ORIENTATION_MAX;
4328 static const int32_t RAW_DISTANCE_MIN;
4329 static const int32_t RAW_DISTANCE_MAX;
4330 static const int32_t RAW_TILT_MIN;
4331 static const int32_t RAW_TILT_MAX;
4332 static const int32_t RAW_ID_MIN;
4333 static const int32_t RAW_ID_MAX;
4334 static const int32_t RAW_SLOT_MIN;
4335 static const int32_t RAW_SLOT_MAX;
4336 static const float X_PRECISION;
4337 static const float Y_PRECISION;
Santos Cordonfa5cf462017-04-05 10:37:00 -07004338 static const float X_PRECISION_VIRTUAL;
4339 static const float Y_PRECISION_VIRTUAL;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004340
4341 static const float GEOMETRIC_SCALE;
Jason Gerecke489fda82012-09-07 17:19:40 -07004342 static const TouchAffineTransformation AFFINE_TRANSFORM;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004343
4344 static const VirtualKeyDefinition VIRTUAL_KEYS[2];
4345
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07004346 const std::string UNIQUE_ID = "local:0";
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004347 const std::string SECONDARY_UNIQUE_ID = "local:1";
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07004348
Michael Wrightd02c5b62014-02-10 15:10:22 -08004349 enum Axes {
4350 POSITION = 1 << 0,
4351 TOUCH = 1 << 1,
4352 TOOL = 1 << 2,
4353 PRESSURE = 1 << 3,
4354 ORIENTATION = 1 << 4,
4355 MINOR = 1 << 5,
4356 ID = 1 << 6,
4357 DISTANCE = 1 << 7,
4358 TILT = 1 << 8,
4359 SLOT = 1 << 9,
4360 TOOL_TYPE = 1 << 10,
4361 };
4362
Michael Wrighta9cf4192022-12-01 23:46:39 +00004363 void prepareDisplay(ui::Rotation orientation, std::optional<uint8_t> port = NO_PORT);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004364 void prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port = NO_PORT);
Michael Wrighta9cf4192022-12-01 23:46:39 +00004365 void prepareVirtualDisplay(ui::Rotation orientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004366 void prepareVirtualKeys();
Jason Gerecke489fda82012-09-07 17:19:40 -07004367 void prepareLocationCalibration();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004368 int32_t toRawX(float displayX);
4369 int32_t toRawY(float displayY);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07004370 int32_t toRotatedRawX(float displayX);
4371 int32_t toRotatedRawY(float displayY);
Jason Gerecke489fda82012-09-07 17:19:40 -07004372 float toCookedX(float rawX, float rawY);
4373 float toCookedY(float rawX, float rawY);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004374 float toDisplayX(int32_t rawX);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004375 float toDisplayX(int32_t rawX, int32_t displayWidth);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004376 float toDisplayY(int32_t rawY);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004377 float toDisplayY(int32_t rawY, int32_t displayHeight);
4378
Michael Wrightd02c5b62014-02-10 15:10:22 -08004379};
4380
4381const int32_t TouchInputMapperTest::RAW_X_MIN = 25;
4382const int32_t TouchInputMapperTest::RAW_X_MAX = 1019;
4383const int32_t TouchInputMapperTest::RAW_Y_MIN = 30;
4384const int32_t TouchInputMapperTest::RAW_Y_MAX = 1009;
4385const int32_t TouchInputMapperTest::RAW_TOUCH_MIN = 0;
4386const int32_t TouchInputMapperTest::RAW_TOUCH_MAX = 31;
4387const int32_t TouchInputMapperTest::RAW_TOOL_MIN = 0;
4388const int32_t TouchInputMapperTest::RAW_TOOL_MAX = 15;
Michael Wrightaa449c92017-12-13 21:21:43 +00004389const int32_t TouchInputMapperTest::RAW_PRESSURE_MIN = 0;
4390const int32_t TouchInputMapperTest::RAW_PRESSURE_MAX = 255;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004391const int32_t TouchInputMapperTest::RAW_ORIENTATION_MIN = -7;
4392const int32_t TouchInputMapperTest::RAW_ORIENTATION_MAX = 7;
4393const int32_t TouchInputMapperTest::RAW_DISTANCE_MIN = 0;
4394const int32_t TouchInputMapperTest::RAW_DISTANCE_MAX = 7;
4395const int32_t TouchInputMapperTest::RAW_TILT_MIN = 0;
4396const int32_t TouchInputMapperTest::RAW_TILT_MAX = 150;
4397const int32_t TouchInputMapperTest::RAW_ID_MIN = 0;
4398const int32_t TouchInputMapperTest::RAW_ID_MAX = 9;
4399const int32_t TouchInputMapperTest::RAW_SLOT_MIN = 0;
4400const int32_t TouchInputMapperTest::RAW_SLOT_MAX = 9;
4401const float TouchInputMapperTest::X_PRECISION = float(RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH;
4402const float TouchInputMapperTest::Y_PRECISION = float(RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT;
Santos Cordonfa5cf462017-04-05 10:37:00 -07004403const float TouchInputMapperTest::X_PRECISION_VIRTUAL =
4404 float(RAW_X_MAX - RAW_X_MIN + 1) / VIRTUAL_DISPLAY_WIDTH;
4405const float TouchInputMapperTest::Y_PRECISION_VIRTUAL =
4406 float(RAW_Y_MAX - RAW_Y_MIN + 1) / VIRTUAL_DISPLAY_HEIGHT;
Jason Gerecke489fda82012-09-07 17:19:40 -07004407const TouchAffineTransformation TouchInputMapperTest::AFFINE_TRANSFORM =
4408 TouchAffineTransformation(1, -2, 3, -4, 5, -6);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004409
4410const float TouchInputMapperTest::GEOMETRIC_SCALE =
4411 avg(float(DISPLAY_WIDTH) / (RAW_X_MAX - RAW_X_MIN + 1),
4412 float(DISPLAY_HEIGHT) / (RAW_Y_MAX - RAW_Y_MIN + 1));
4413
4414const VirtualKeyDefinition TouchInputMapperTest::VIRTUAL_KEYS[2] = {
4415 { KEY_HOME, 60, DISPLAY_HEIGHT + 15, 20, 20 },
4416 { KEY_MENU, DISPLAY_HEIGHT - 60, DISPLAY_WIDTH + 15, 20, 20 },
4417};
4418
Michael Wrighta9cf4192022-12-01 23:46:39 +00004419void TouchInputMapperTest::prepareDisplay(ui::Rotation orientation, std::optional<uint8_t> port) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01004420 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
4421 port, ViewportType::INTERNAL);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004422}
4423
4424void TouchInputMapperTest::prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port) {
4425 setDisplayInfoAndReconfigure(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00004426 ui::ROTATION_0, SECONDARY_UNIQUE_ID, port, type);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004427}
4428
Michael Wrighta9cf4192022-12-01 23:46:39 +00004429void TouchInputMapperTest::prepareVirtualDisplay(ui::Rotation orientation) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01004430 setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH, VIRTUAL_DISPLAY_HEIGHT,
4431 orientation, VIRTUAL_DISPLAY_UNIQUE_ID, NO_PORT,
4432 ViewportType::VIRTUAL);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004433}
4434
Michael Wrightd02c5b62014-02-10 15:10:22 -08004435void TouchInputMapperTest::prepareVirtualKeys() {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004436 mFakeEventHub->addVirtualKeyDefinition(EVENTHUB_ID, VIRTUAL_KEYS[0]);
4437 mFakeEventHub->addVirtualKeyDefinition(EVENTHUB_ID, VIRTUAL_KEYS[1]);
4438 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4439 mFakeEventHub->addKey(EVENTHUB_ID, KEY_MENU, 0, AKEYCODE_MENU, POLICY_FLAG_WAKE);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004440}
4441
Jason Gerecke489fda82012-09-07 17:19:40 -07004442void TouchInputMapperTest::prepareLocationCalibration() {
4443 mFakePolicy->setTouchAffineTransformation(AFFINE_TRANSFORM);
4444}
4445
Michael Wrightd02c5b62014-02-10 15:10:22 -08004446int32_t TouchInputMapperTest::toRawX(float displayX) {
4447 return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH + RAW_X_MIN);
4448}
4449
4450int32_t TouchInputMapperTest::toRawY(float displayY) {
4451 return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT + RAW_Y_MIN);
4452}
4453
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07004454int32_t TouchInputMapperTest::toRotatedRawX(float displayX) {
4455 return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_HEIGHT + RAW_X_MIN);
4456}
4457
4458int32_t TouchInputMapperTest::toRotatedRawY(float displayY) {
4459 return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_WIDTH + RAW_Y_MIN);
4460}
4461
Jason Gerecke489fda82012-09-07 17:19:40 -07004462float TouchInputMapperTest::toCookedX(float rawX, float rawY) {
4463 AFFINE_TRANSFORM.applyTo(rawX, rawY);
4464 return rawX;
4465}
4466
4467float TouchInputMapperTest::toCookedY(float rawX, float rawY) {
4468 AFFINE_TRANSFORM.applyTo(rawX, rawY);
4469 return rawY;
4470}
4471
Michael Wrightd02c5b62014-02-10 15:10:22 -08004472float TouchInputMapperTest::toDisplayX(int32_t rawX) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004473 return toDisplayX(rawX, DISPLAY_WIDTH);
4474}
4475
4476float TouchInputMapperTest::toDisplayX(int32_t rawX, int32_t displayWidth) {
4477 return float(rawX - RAW_X_MIN) * displayWidth / (RAW_X_MAX - RAW_X_MIN + 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004478}
4479
4480float TouchInputMapperTest::toDisplayY(int32_t rawY) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004481 return toDisplayY(rawY, DISPLAY_HEIGHT);
4482}
4483
4484float TouchInputMapperTest::toDisplayY(int32_t rawY, int32_t displayHeight) {
4485 return float(rawY - RAW_Y_MIN) * displayHeight / (RAW_Y_MAX - RAW_Y_MIN + 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004486}
4487
4488
4489// --- SingleTouchInputMapperTest ---
4490
4491class SingleTouchInputMapperTest : public TouchInputMapperTest {
4492protected:
4493 void prepareButtons();
4494 void prepareAxes(int axes);
4495
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004496 std::list<NotifyArgs> processDown(SingleTouchInputMapper& mapper, int32_t x, int32_t y);
4497 std::list<NotifyArgs> processMove(SingleTouchInputMapper& mapper, int32_t x, int32_t y);
4498 std::list<NotifyArgs> processUp(SingleTouchInputMapper& mappery);
4499 std::list<NotifyArgs> processPressure(SingleTouchInputMapper& mapper, int32_t pressure);
4500 std::list<NotifyArgs> processToolMajor(SingleTouchInputMapper& mapper, int32_t toolMajor);
4501 std::list<NotifyArgs> processDistance(SingleTouchInputMapper& mapper, int32_t distance);
4502 std::list<NotifyArgs> processTilt(SingleTouchInputMapper& mapper, int32_t tiltX, int32_t tiltY);
4503 std::list<NotifyArgs> processKey(SingleTouchInputMapper& mapper, int32_t code, int32_t value);
4504 std::list<NotifyArgs> processSync(SingleTouchInputMapper& mapper);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004505};
4506
4507void SingleTouchInputMapperTest::prepareButtons() {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004508 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004509}
4510
4511void SingleTouchInputMapperTest::prepareAxes(int axes) {
4512 if (axes & POSITION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004513 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
4514 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004515 }
4516 if (axes & PRESSURE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004517 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_PRESSURE, RAW_PRESSURE_MIN,
4518 RAW_PRESSURE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004519 }
4520 if (axes & TOOL) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004521 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TOOL_WIDTH, RAW_TOOL_MIN, RAW_TOOL_MAX, 0,
4522 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004523 }
4524 if (axes & DISTANCE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004525 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_DISTANCE, RAW_DISTANCE_MIN,
4526 RAW_DISTANCE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004527 }
4528 if (axes & TILT) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004529 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TILT_X, RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
4530 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TILT_Y, RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004531 }
4532}
4533
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004534std::list<NotifyArgs> SingleTouchInputMapperTest::processDown(SingleTouchInputMapper& mapper,
4535 int32_t x, int32_t y) {
4536 std::list<NotifyArgs> args;
4537 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
4538 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, x);
4539 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, y);
4540 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004541}
4542
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004543std::list<NotifyArgs> SingleTouchInputMapperTest::processMove(SingleTouchInputMapper& mapper,
4544 int32_t x, int32_t y) {
4545 std::list<NotifyArgs> args;
4546 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, x);
4547 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, y);
4548 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004549}
4550
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004551std::list<NotifyArgs> SingleTouchInputMapperTest::processUp(SingleTouchInputMapper& mapper) {
4552 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004553}
4554
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004555std::list<NotifyArgs> SingleTouchInputMapperTest::processPressure(SingleTouchInputMapper& mapper,
4556 int32_t pressure) {
4557 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_PRESSURE, pressure);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004558}
4559
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004560std::list<NotifyArgs> SingleTouchInputMapperTest::processToolMajor(SingleTouchInputMapper& mapper,
4561 int32_t toolMajor) {
4562 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TOOL_WIDTH, toolMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004563}
4564
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004565std::list<NotifyArgs> SingleTouchInputMapperTest::processDistance(SingleTouchInputMapper& mapper,
4566 int32_t distance) {
4567 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_DISTANCE, distance);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004568}
4569
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004570std::list<NotifyArgs> SingleTouchInputMapperTest::processTilt(SingleTouchInputMapper& mapper,
4571 int32_t tiltX, int32_t tiltY) {
4572 std::list<NotifyArgs> args;
4573 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TILT_X, tiltX);
4574 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TILT_Y, tiltY);
4575 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004576}
4577
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004578std::list<NotifyArgs> SingleTouchInputMapperTest::processKey(SingleTouchInputMapper& mapper,
4579 int32_t code, int32_t value) {
4580 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004581}
4582
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004583std::list<NotifyArgs> SingleTouchInputMapperTest::processSync(SingleTouchInputMapper& mapper) {
4584 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004585}
4586
Michael Wrightd02c5b62014-02-10 15:10:22 -08004587TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndNotACursor_ReturnsPointer) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004588 prepareButtons();
4589 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00004590 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004591
Josep del Río2d8c79a2023-01-23 19:33:50 +00004592 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004593}
4594
Michael Wrightd02c5b62014-02-10 15:10:22 -08004595TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004596 prepareButtons();
4597 prepareAxes(POSITION);
4598 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00004599 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004600
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004601 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004602}
4603
4604TEST_F(SingleTouchInputMapperTest, GetKeyCodeState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004605 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004606 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004607 prepareButtons();
4608 prepareAxes(POSITION);
4609 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004610 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004611
4612 // Unknown key.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004613 ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004614
4615 // Virtual key is down.
4616 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4617 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4618 processDown(mapper, x, y);
4619 processSync(mapper);
4620 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4621
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004622 ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004623
4624 // Virtual key is up.
4625 processUp(mapper);
4626 processSync(mapper);
4627 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4628
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004629 ASSERT_EQ(AKEY_STATE_UP, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004630}
4631
4632TEST_F(SingleTouchInputMapperTest, GetScanCodeState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004633 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004634 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004635 prepareButtons();
4636 prepareAxes(POSITION);
4637 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004638 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004639
4640 // Unknown key.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004641 ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004642
4643 // Virtual key is down.
4644 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4645 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4646 processDown(mapper, x, y);
4647 processSync(mapper);
4648 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4649
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004650 ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004651
4652 // Virtual key is up.
4653 processUp(mapper);
4654 processSync(mapper);
4655 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4656
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004657 ASSERT_EQ(AKEY_STATE_UP, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004658}
4659
4660TEST_F(SingleTouchInputMapperTest, MarkSupportedKeyCodes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004661 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004662 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004663 prepareButtons();
4664 prepareAxes(POSITION);
4665 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004666 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004667
Michael Wrightd02c5b62014-02-10 15:10:22 -08004668 uint8_t flags[2] = { 0, 0 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07004669 ASSERT_TRUE(
4670 mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_HOME, AKEYCODE_A}, flags));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004671 ASSERT_TRUE(flags[0]);
4672 ASSERT_FALSE(flags[1]);
4673}
4674
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004675TEST_F(SingleTouchInputMapperTest, DeviceTypeChange_RecalculatesRawToDisplayTransform) {
4676 prepareDisplay(ui::ROTATION_0);
4677 prepareAxes(POSITION);
4678 addConfigurationProperty("touch.deviceType", "touchScreen");
4679 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
4680
4681 const int32_t x = 900;
4682 const int32_t y = 75;
4683 std::list<NotifyArgs> args;
4684 args += processDown(mapper, x, y);
4685 args += processSync(mapper);
4686
4687 // Assert that motion event is received in display coordinate space for deviceType touchScreen.
4688 ASSERT_THAT(args,
4689 ElementsAre(VariantWith<NotifyMotionArgs>(
4690 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4691 WithCoords(toDisplayX(x), toDisplayY(y))))));
4692
4693 // Add device type association after the device was created.
4694 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
4695 // Send update to the mapper.
4696 std::list<NotifyArgs> unused =
4697 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
4698 InputReaderConfiguration::Change::DEVICE_TYPE /*changes*/);
4699
4700 args.clear();
4701 args += processDown(mapper, x, y);
4702 args += processSync(mapper);
4703
4704 // Assert that motion event is received in raw coordinate space for deviceType touchNavigation.
4705 ASSERT_THAT(args,
4706 ElementsAre(VariantWith<NotifyMotionArgs>(
4707 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4708 WithCoords(x - RAW_X_MIN, y - RAW_Y_MIN)))));
4709}
4710
Michael Wrightd02c5b62014-02-10 15:10:22 -08004711TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNormally_SendsKeyDownAndKeyUp) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004712 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004713 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004714 prepareButtons();
4715 prepareAxes(POSITION);
4716 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004717 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004718
arthurhungdcef2dc2020-08-11 14:47:50 +08004719 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004720
4721 NotifyKeyArgs args;
4722
4723 // Press virtual key.
4724 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4725 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4726 processDown(mapper, x, y);
4727 processSync(mapper);
4728
4729 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4730 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4731 ASSERT_EQ(DEVICE_ID, args.deviceId);
4732 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4733 ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
4734 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
4735 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
4736 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4737 ASSERT_EQ(KEY_HOME, args.scanCode);
4738 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
4739 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
4740
4741 // Release virtual key.
4742 processUp(mapper);
4743 processSync(mapper);
4744
4745 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4746 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4747 ASSERT_EQ(DEVICE_ID, args.deviceId);
4748 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4749 ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
4750 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
4751 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
4752 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4753 ASSERT_EQ(KEY_HOME, args.scanCode);
4754 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
4755 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
4756
4757 // Should not have sent any motions.
4758 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4759}
4760
4761TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfBounds_SendsKeyDownAndKeyCancel) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004762 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004763 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004764 prepareButtons();
4765 prepareAxes(POSITION);
4766 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004767 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004768
arthurhungdcef2dc2020-08-11 14:47:50 +08004769 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004770
4771 NotifyKeyArgs keyArgs;
4772
4773 // Press virtual key.
4774 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4775 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4776 processDown(mapper, x, y);
4777 processSync(mapper);
4778
4779 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
4780 ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
4781 ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
4782 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
4783 ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
4784 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
4785 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, keyArgs.flags);
4786 ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
4787 ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
4788 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
4789 ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
4790
4791 // Move out of bounds. This should generate a cancel and a pointer down since we moved
4792 // into the display area.
4793 y -= 100;
4794 processMove(mapper, x, y);
4795 processSync(mapper);
4796
4797 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
4798 ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
4799 ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
4800 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
4801 ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
4802 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
4803 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
4804 | AKEY_EVENT_FLAG_CANCELED, keyArgs.flags);
4805 ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
4806 ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
4807 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
4808 ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
4809
4810 NotifyMotionArgs motionArgs;
4811 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4812 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4813 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4814 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4815 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4816 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4817 ASSERT_EQ(0, motionArgs.flags);
4818 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4819 ASSERT_EQ(0, motionArgs.buttonState);
4820 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004821 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004822 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004823 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004824 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4825 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4826 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4827 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4828 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4829
4830 // Keep moving out of bounds. Should generate a pointer move.
4831 y -= 50;
4832 processMove(mapper, x, y);
4833 processSync(mapper);
4834
4835 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4836 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4837 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4838 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4839 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4840 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
4841 ASSERT_EQ(0, motionArgs.flags);
4842 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4843 ASSERT_EQ(0, motionArgs.buttonState);
4844 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004845 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004846 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004847 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004848 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4849 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4850 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4851 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4852 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4853
4854 // Release out of bounds. Should generate a pointer up.
4855 processUp(mapper);
4856 processSync(mapper);
4857
4858 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4859 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4860 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4861 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4862 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4863 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4864 ASSERT_EQ(0, motionArgs.flags);
4865 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4866 ASSERT_EQ(0, motionArgs.buttonState);
4867 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004868 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004869 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004870 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004871 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4872 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4873 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4874 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4875 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4876
4877 // Should not have sent any more keys or motions.
4878 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4879 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4880}
4881
4882TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMovesIn_SendsDownAsTouchEntersDisplay) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004883 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004884 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004885 prepareButtons();
4886 prepareAxes(POSITION);
4887 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004888 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004889
arthurhungdcef2dc2020-08-11 14:47:50 +08004890 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004891
4892 NotifyMotionArgs motionArgs;
4893
4894 // Initially go down out of bounds.
4895 int32_t x = -10;
4896 int32_t y = -10;
4897 processDown(mapper, x, y);
4898 processSync(mapper);
4899
4900 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4901
4902 // Move into the display area. Should generate a pointer down.
4903 x = 50;
4904 y = 75;
4905 processMove(mapper, x, y);
4906 processSync(mapper);
4907
4908 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4909 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4910 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4911 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4912 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4913 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4914 ASSERT_EQ(0, motionArgs.flags);
4915 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4916 ASSERT_EQ(0, motionArgs.buttonState);
4917 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004918 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004919 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004920 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004921 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4922 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4923 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4924 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4925 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4926
4927 // Release. Should generate a pointer up.
4928 processUp(mapper);
4929 processSync(mapper);
4930
4931 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4932 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4933 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4934 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4935 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4936 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4937 ASSERT_EQ(0, motionArgs.flags);
4938 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4939 ASSERT_EQ(0, motionArgs.buttonState);
4940 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004941 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004942 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004943 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004944 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4945 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4946 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4947 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4948 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4949
4950 // Should not have sent any more keys or motions.
4951 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4952 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4953}
4954
Santos Cordonfa5cf462017-04-05 10:37:00 -07004955TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture_VirtualDisplay) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004956 addConfigurationProperty("touch.deviceType", "touchScreen");
4957 addConfigurationProperty("touch.displayId", VIRTUAL_DISPLAY_UNIQUE_ID);
4958
Michael Wrighta9cf4192022-12-01 23:46:39 +00004959 prepareVirtualDisplay(ui::ROTATION_0);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004960 prepareButtons();
4961 prepareAxes(POSITION);
4962 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004963 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Santos Cordonfa5cf462017-04-05 10:37:00 -07004964
arthurhungdcef2dc2020-08-11 14:47:50 +08004965 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004966
4967 NotifyMotionArgs motionArgs;
4968
4969 // Down.
4970 int32_t x = 100;
4971 int32_t y = 125;
4972 processDown(mapper, x, y);
4973 processSync(mapper);
4974
4975 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4976 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4977 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4978 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4979 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4980 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4981 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4982 ASSERT_EQ(0, motionArgs.flags);
4983 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4984 ASSERT_EQ(0, motionArgs.buttonState);
4985 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004986 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004987 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004988 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004989 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4990 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4991 1, 0, 0, 0, 0, 0, 0, 0));
4992 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4993 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4994 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4995
4996 // Move.
4997 x += 50;
4998 y += 75;
4999 processMove(mapper, x, y);
5000 processSync(mapper);
5001
5002 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5003 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5004 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5005 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
5006 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5007 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5008 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5009 ASSERT_EQ(0, motionArgs.flags);
5010 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5011 ASSERT_EQ(0, motionArgs.buttonState);
5012 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005013 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07005014 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005015 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07005016 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5017 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
5018 1, 0, 0, 0, 0, 0, 0, 0));
5019 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
5020 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
5021 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5022
5023 // Up.
5024 processUp(mapper);
5025 processSync(mapper);
5026
5027 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5028 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5029 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5030 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
5031 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5032 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5033 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5034 ASSERT_EQ(0, motionArgs.flags);
5035 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5036 ASSERT_EQ(0, motionArgs.buttonState);
5037 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005038 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07005039 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005040 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07005041 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5042 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
5043 1, 0, 0, 0, 0, 0, 0, 0));
5044 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
5045 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
5046 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5047
5048 // Should not have sent any more keys or motions.
5049 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5050 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5051}
5052
Michael Wrightd02c5b62014-02-10 15:10:22 -08005053TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005054 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005055 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005056 prepareButtons();
5057 prepareAxes(POSITION);
5058 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00005059 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005060
arthurhungdcef2dc2020-08-11 14:47:50 +08005061 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005062
5063 NotifyMotionArgs motionArgs;
5064
5065 // Down.
5066 int32_t x = 100;
5067 int32_t y = 125;
5068 processDown(mapper, x, y);
5069 processSync(mapper);
5070
5071 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5072 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5073 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5074 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5075 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5076 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5077 ASSERT_EQ(0, motionArgs.flags);
5078 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5079 ASSERT_EQ(0, motionArgs.buttonState);
5080 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005081 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08005082 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005083 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005084 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5085 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
5086 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5087 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5088 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5089
5090 // Move.
5091 x += 50;
5092 y += 75;
5093 processMove(mapper, x, y);
5094 processSync(mapper);
5095
5096 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5097 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5098 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5099 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5100 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5101 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5102 ASSERT_EQ(0, motionArgs.flags);
5103 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5104 ASSERT_EQ(0, motionArgs.buttonState);
5105 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005106 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08005107 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005108 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005109 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5110 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
5111 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5112 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5113 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5114
5115 // Up.
5116 processUp(mapper);
5117 processSync(mapper);
5118
5119 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5120 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5121 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5122 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5123 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5124 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5125 ASSERT_EQ(0, motionArgs.flags);
5126 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5127 ASSERT_EQ(0, motionArgs.buttonState);
5128 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005129 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08005130 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005131 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005132 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5133 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
5134 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5135 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5136 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5137
5138 // Should not have sent any more keys or motions.
5139 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5140 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5141}
5142
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005143TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_DoesNotRotateMotions) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005144 addConfigurationProperty("touch.deviceType", "touchScreen");
5145 prepareButtons();
5146 prepareAxes(POSITION);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005147 // InputReader works in the un-rotated coordinate space, so orientation-aware devices do not
5148 // need to be rotated. Touchscreens are orientation-aware by default.
Arpit Singha8c236b2023-04-25 13:56:05 +00005149 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005150
5151 NotifyMotionArgs args;
5152
5153 // Rotation 90.
Michael Wrighta9cf4192022-12-01 23:46:39 +00005154 prepareDisplay(ui::ROTATION_90);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005155 processDown(mapper, toRawX(50), toRawY(75));
5156 processSync(mapper);
5157
5158 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5159 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5160 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5161
5162 processUp(mapper);
5163 processSync(mapper);
5164 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5165}
5166
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005167TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_RotatesMotions) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005168 addConfigurationProperty("touch.deviceType", "touchScreen");
5169 prepareButtons();
5170 prepareAxes(POSITION);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005171 // Since InputReader works in the un-rotated coordinate space, only devices that are not
5172 // orientation-aware are affected by display rotation.
5173 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00005174 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005175
5176 NotifyMotionArgs args;
5177
5178 // Rotation 0.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005179 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005180 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005181 processDown(mapper, toRawX(50), toRawY(75));
5182 processSync(mapper);
5183
5184 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5185 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5186 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5187
5188 processUp(mapper);
5189 processSync(mapper);
5190 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5191
5192 // Rotation 90.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005193 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005194 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005195 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005196 processSync(mapper);
5197
5198 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5199 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5200 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5201
5202 processUp(mapper);
5203 processSync(mapper);
5204 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5205
5206 // Rotation 180.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005207 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005208 prepareDisplay(ui::ROTATION_180);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005209 processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
5210 processSync(mapper);
5211
5212 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5213 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5214 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5215
5216 processUp(mapper);
5217 processSync(mapper);
5218 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5219
5220 // Rotation 270.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005221 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005222 prepareDisplay(ui::ROTATION_270);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005223 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005224 processSync(mapper);
5225
5226 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5227 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5228 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5229
5230 processUp(mapper);
5231 processSync(mapper);
5232 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5233}
5234
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005235TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation0_RotatesMotions) {
5236 addConfigurationProperty("touch.deviceType", "touchScreen");
5237 prepareButtons();
5238 prepareAxes(POSITION);
5239 addConfigurationProperty("touch.orientationAware", "1");
5240 addConfigurationProperty("touch.orientation", "ORIENTATION_0");
5241 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005242 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005243 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005244 NotifyMotionArgs args;
5245
5246 // Orientation 0.
5247 processDown(mapper, toRawX(50), toRawY(75));
5248 processSync(mapper);
5249
5250 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5251 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5252 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5253
5254 processUp(mapper);
5255 processSync(mapper);
5256 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5257}
5258
5259TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation90_RotatesMotions) {
5260 addConfigurationProperty("touch.deviceType", "touchScreen");
5261 prepareButtons();
5262 prepareAxes(POSITION);
5263 addConfigurationProperty("touch.orientationAware", "1");
5264 addConfigurationProperty("touch.orientation", "ORIENTATION_90");
5265 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005266 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005267 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005268 NotifyMotionArgs args;
5269
5270 // Orientation 90.
5271 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
5272 processSync(mapper);
5273
5274 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5275 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5276 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5277
5278 processUp(mapper);
5279 processSync(mapper);
5280 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5281}
5282
5283TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation180_RotatesMotions) {
5284 addConfigurationProperty("touch.deviceType", "touchScreen");
5285 prepareButtons();
5286 prepareAxes(POSITION);
5287 addConfigurationProperty("touch.orientationAware", "1");
5288 addConfigurationProperty("touch.orientation", "ORIENTATION_180");
5289 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005290 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005291 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005292 NotifyMotionArgs args;
5293
5294 // Orientation 180.
5295 processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
5296 processSync(mapper);
5297
5298 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5299 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5300 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5301
5302 processUp(mapper);
5303 processSync(mapper);
5304 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5305}
5306
5307TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation270_RotatesMotions) {
5308 addConfigurationProperty("touch.deviceType", "touchScreen");
5309 prepareButtons();
5310 prepareAxes(POSITION);
5311 addConfigurationProperty("touch.orientationAware", "1");
5312 addConfigurationProperty("touch.orientation", "ORIENTATION_270");
5313 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005314 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005315 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005316 NotifyMotionArgs args;
5317
5318 // Orientation 270.
5319 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
5320 processSync(mapper);
5321
5322 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5323 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5324 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5325
5326 processUp(mapper);
5327 processSync(mapper);
5328 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5329}
5330
5331TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationSpecified_RotatesMotionWithDisplay) {
5332 addConfigurationProperty("touch.deviceType", "touchScreen");
5333 prepareButtons();
5334 prepareAxes(POSITION);
5335 // Since InputReader works in the un-rotated coordinate space, only devices that are not
5336 // orientation-aware are affected by display rotation.
5337 addConfigurationProperty("touch.orientationAware", "0");
5338 addConfigurationProperty("touch.orientation", "ORIENTATION_90");
Arpit Singha8c236b2023-04-25 13:56:05 +00005339 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005340
5341 NotifyMotionArgs args;
5342
5343 // Orientation 90, Rotation 0.
5344 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005345 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005346 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
5347 processSync(mapper);
5348
5349 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5350 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5351 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5352
5353 processUp(mapper);
5354 processSync(mapper);
5355 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5356
5357 // Orientation 90, Rotation 90.
5358 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005359 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005360 processDown(mapper, toRawX(50), toRawY(75));
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005361 processSync(mapper);
5362
5363 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5364 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5365 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5366
5367 processUp(mapper);
5368 processSync(mapper);
5369 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5370
5371 // Orientation 90, Rotation 180.
5372 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005373 prepareDisplay(ui::ROTATION_180);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005374 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
5375 processSync(mapper);
5376
5377 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5378 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5379 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5380
5381 processUp(mapper);
5382 processSync(mapper);
5383 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5384
5385 // Orientation 90, Rotation 270.
5386 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005387 prepareDisplay(ui::ROTATION_270);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005388 processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005389 processSync(mapper);
5390
5391 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5392 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5393 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5394
5395 processUp(mapper);
5396 processSync(mapper);
5397 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5398}
5399
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005400TEST_F(SingleTouchInputMapperTest, Process_IgnoresTouchesOutsidePhysicalFrame) {
5401 addConfigurationProperty("touch.deviceType", "touchScreen");
5402 prepareButtons();
5403 prepareAxes(POSITION);
5404 addConfigurationProperty("touch.orientationAware", "1");
5405 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005406 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005407
5408 // Set a physical frame in the display viewport.
5409 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
5410 viewport->physicalLeft = 20;
5411 viewport->physicalTop = 600;
5412 viewport->physicalRight = 30;
5413 viewport->physicalBottom = 610;
5414 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00005415 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005416
5417 // Start the touch.
5418 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
5419 processSync(mapper);
5420
5421 // Expect all input starting outside the physical frame to be ignored.
5422 const std::array<Point, 6> outsidePoints = {
5423 {{0, 0}, {19, 605}, {31, 605}, {25, 599}, {25, 611}, {DISPLAY_WIDTH, DISPLAY_HEIGHT}}};
5424 for (const auto& p : outsidePoints) {
5425 processMove(mapper, toRawX(p.x), toRawY(p.y));
5426 processSync(mapper);
5427 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5428 }
5429
5430 // Move the touch into the physical frame.
5431 processMove(mapper, toRawX(25), toRawY(605));
5432 processSync(mapper);
5433 NotifyMotionArgs args;
5434 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5435 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
5436 EXPECT_NEAR(25, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5437 EXPECT_NEAR(605, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5438
5439 // Once the touch down is reported, continue reporting input, even if it is outside the frame.
5440 for (const auto& p : outsidePoints) {
5441 processMove(mapper, toRawX(p.x), toRawY(p.y));
5442 processSync(mapper);
5443 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5444 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
5445 EXPECT_NEAR(p.x, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5446 EXPECT_NEAR(p.y, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5447 }
5448
5449 processUp(mapper);
5450 processSync(mapper);
5451 EXPECT_NO_FATAL_FAILURE(
5452 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
5453}
5454
Harry Cutts1db43992023-06-19 17:05:07 +00005455TEST_F(SingleTouchInputMapperTest, Process_DoesntCheckPhysicalFrameForTouchpads) {
Harry Cutts1db43992023-06-19 17:05:07 +00005456 addConfigurationProperty("touch.deviceType", "pointer");
5457 prepareAxes(POSITION);
5458 prepareDisplay(ui::ROTATION_0);
5459 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
5460
5461 // Set a physical frame in the display viewport.
5462 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
5463 viewport->physicalLeft = 20;
5464 viewport->physicalTop = 600;
5465 viewport->physicalRight = 30;
5466 viewport->physicalBottom = 610;
5467 mFakePolicy->updateViewport(*viewport);
5468 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
5469
5470 // Start the touch.
5471 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
5472 processSync(mapper);
5473
5474 // Expect all input starting outside the physical frame to result in NotifyMotionArgs being
5475 // produced.
5476 const std::array<Point, 6> outsidePoints = {
5477 {{0, 0}, {19, 605}, {31, 605}, {25, 599}, {25, 611}, {DISPLAY_WIDTH, DISPLAY_HEIGHT}}};
5478 for (const auto& p : outsidePoints) {
5479 processMove(mapper, toRawX(p.x), toRawY(p.y));
5480 processSync(mapper);
5481 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5482 }
5483}
5484
Michael Wrightd02c5b62014-02-10 15:10:22 -08005485TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005486 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005487 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005488 prepareButtons();
5489 prepareAxes(POSITION | PRESSURE | TOOL | DISTANCE | TILT);
Arpit Singha8c236b2023-04-25 13:56:05 +00005490 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005491
5492 // These calculations are based on the input device calibration documentation.
5493 int32_t rawX = 100;
5494 int32_t rawY = 200;
5495 int32_t rawPressure = 10;
5496 int32_t rawToolMajor = 12;
5497 int32_t rawDistance = 2;
5498 int32_t rawTiltX = 30;
5499 int32_t rawTiltY = 110;
5500
5501 float x = toDisplayX(rawX);
5502 float y = toDisplayY(rawY);
5503 float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
5504 float size = float(rawToolMajor) / RAW_TOOL_MAX;
5505 float tool = float(rawToolMajor) * GEOMETRIC_SCALE;
5506 float distance = float(rawDistance);
5507
5508 float tiltCenter = (RAW_TILT_MAX + RAW_TILT_MIN) * 0.5f;
5509 float tiltScale = M_PI / 180;
5510 float tiltXAngle = (rawTiltX - tiltCenter) * tiltScale;
5511 float tiltYAngle = (rawTiltY - tiltCenter) * tiltScale;
5512 float orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
5513 float tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
5514
5515 processDown(mapper, rawX, rawY);
5516 processPressure(mapper, rawPressure);
5517 processToolMajor(mapper, rawToolMajor);
5518 processDistance(mapper, rawDistance);
5519 processTilt(mapper, rawTiltX, rawTiltY);
5520 processSync(mapper);
5521
5522 NotifyMotionArgs args;
5523 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5524 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
5525 x, y, pressure, size, tool, tool, tool, tool, orientation, distance));
5526 ASSERT_EQ(tilt, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TILT));
Prabir Pradhan9a53b552024-06-04 02:59:40 +00005527 ASSERT_EQ(args.flags,
5528 AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION |
5529 AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005530}
5531
Jason Gerecke489fda82012-09-07 17:19:40 -07005532TEST_F(SingleTouchInputMapperTest, Process_XYAxes_AffineCalibration) {
Jason Gerecke489fda82012-09-07 17:19:40 -07005533 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005534 prepareDisplay(ui::ROTATION_0);
Jason Gerecke489fda82012-09-07 17:19:40 -07005535 prepareLocationCalibration();
5536 prepareButtons();
5537 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005538 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Jason Gerecke489fda82012-09-07 17:19:40 -07005539
5540 int32_t rawX = 100;
5541 int32_t rawY = 200;
5542
5543 float x = toDisplayX(toCookedX(rawX, rawY));
5544 float y = toDisplayY(toCookedY(rawX, rawY));
5545
5546 processDown(mapper, rawX, rawY);
5547 processSync(mapper);
5548
5549 NotifyMotionArgs args;
5550 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5551 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
5552 x, y, 1, 0, 0, 0, 0, 0, 0, 0));
5553}
5554
Michael Wrightd02c5b62014-02-10 15:10:22 -08005555TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllButtons) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005556 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005557 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005558 prepareButtons();
5559 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005560 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005561
5562 NotifyMotionArgs motionArgs;
5563 NotifyKeyArgs keyArgs;
5564
5565 processDown(mapper, 100, 200);
5566 processSync(mapper);
5567 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5568 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5569 ASSERT_EQ(0, motionArgs.buttonState);
5570
5571 // press BTN_LEFT, release BTN_LEFT
5572 processKey(mapper, BTN_LEFT, 1);
5573 processSync(mapper);
5574 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5575 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5576 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
5577
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005578 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5579 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5580 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
5581
Michael Wrightd02c5b62014-02-10 15:10:22 -08005582 processKey(mapper, BTN_LEFT, 0);
5583 processSync(mapper);
5584 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005585 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005586 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005587
5588 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005589 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005590 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005591
5592 // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
5593 processKey(mapper, BTN_RIGHT, 1);
5594 processKey(mapper, BTN_MIDDLE, 1);
5595 processSync(mapper);
5596 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5597 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5598 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
5599 motionArgs.buttonState);
5600
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005601 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5602 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5603 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
5604
5605 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5606 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5607 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
5608 motionArgs.buttonState);
5609
Michael Wrightd02c5b62014-02-10 15:10:22 -08005610 processKey(mapper, BTN_RIGHT, 0);
5611 processSync(mapper);
5612 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005613 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005614 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005615
5616 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005617 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005618 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005619
5620 processKey(mapper, BTN_MIDDLE, 0);
5621 processSync(mapper);
5622 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005623 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005624 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005625
5626 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005627 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005628 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005629
5630 // press BTN_BACK, release BTN_BACK
5631 processKey(mapper, BTN_BACK, 1);
5632 processSync(mapper);
5633 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5634 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5635 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005636
Michael Wrightd02c5b62014-02-10 15:10:22 -08005637 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005638 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005639 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
5640
5641 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5642 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5643 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005644
5645 processKey(mapper, BTN_BACK, 0);
5646 processSync(mapper);
5647 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005648 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005649 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005650
5651 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005652 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005653 ASSERT_EQ(0, motionArgs.buttonState);
5654
Michael Wrightd02c5b62014-02-10 15:10:22 -08005655 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5656 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5657 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
5658
5659 // press BTN_SIDE, release BTN_SIDE
5660 processKey(mapper, BTN_SIDE, 1);
5661 processSync(mapper);
5662 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5663 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5664 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005665
Michael Wrightd02c5b62014-02-10 15:10:22 -08005666 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005667 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005668 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
5669
5670 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5671 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5672 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005673
5674 processKey(mapper, BTN_SIDE, 0);
5675 processSync(mapper);
5676 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005677 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005678 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005679
5680 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005681 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005682 ASSERT_EQ(0, motionArgs.buttonState);
5683
Michael Wrightd02c5b62014-02-10 15:10:22 -08005684 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5685 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5686 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
5687
5688 // press BTN_FORWARD, release BTN_FORWARD
5689 processKey(mapper, BTN_FORWARD, 1);
5690 processSync(mapper);
5691 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5692 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5693 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005694
Michael Wrightd02c5b62014-02-10 15:10:22 -08005695 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005696 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005697 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
5698
5699 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5700 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5701 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005702
5703 processKey(mapper, BTN_FORWARD, 0);
5704 processSync(mapper);
5705 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005706 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005707 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005708
5709 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005710 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005711 ASSERT_EQ(0, motionArgs.buttonState);
5712
Michael Wrightd02c5b62014-02-10 15:10:22 -08005713 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5714 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5715 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
5716
5717 // press BTN_EXTRA, release BTN_EXTRA
5718 processKey(mapper, BTN_EXTRA, 1);
5719 processSync(mapper);
5720 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5721 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5722 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005723
Michael Wrightd02c5b62014-02-10 15:10:22 -08005724 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005725 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005726 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
5727
5728 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5729 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5730 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005731
5732 processKey(mapper, BTN_EXTRA, 0);
5733 processSync(mapper);
5734 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005735 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005736 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005737
5738 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005739 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005740 ASSERT_EQ(0, motionArgs.buttonState);
5741
Michael Wrightd02c5b62014-02-10 15:10:22 -08005742 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5743 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5744 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
5745
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005746 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5747
Michael Wrightd02c5b62014-02-10 15:10:22 -08005748 // press BTN_STYLUS, release BTN_STYLUS
5749 processKey(mapper, BTN_STYLUS, 1);
5750 processSync(mapper);
5751 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5752 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005753 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
5754
5755 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5756 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5757 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005758
5759 processKey(mapper, BTN_STYLUS, 0);
5760 processSync(mapper);
5761 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005762 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005763 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005764
5765 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005766 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005767 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005768
5769 // press BTN_STYLUS2, release BTN_STYLUS2
5770 processKey(mapper, BTN_STYLUS2, 1);
5771 processSync(mapper);
5772 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5773 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005774 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
5775
5776 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5777 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5778 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005779
5780 processKey(mapper, BTN_STYLUS2, 0);
5781 processSync(mapper);
5782 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005783 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005784 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005785
5786 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005787 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005788 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005789
5790 // release touch
5791 processUp(mapper);
5792 processSync(mapper);
5793 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5794 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5795 ASSERT_EQ(0, motionArgs.buttonState);
5796}
5797
5798TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005799 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005800 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005801 prepareButtons();
5802 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005803 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005804
5805 NotifyMotionArgs motionArgs;
5806
5807 // default tool type is finger
5808 processDown(mapper, 100, 200);
5809 processSync(mapper);
5810 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5811 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005812 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005813
5814 // eraser
5815 processKey(mapper, BTN_TOOL_RUBBER, 1);
5816 processSync(mapper);
5817 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5818 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005819 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005820
5821 // stylus
5822 processKey(mapper, BTN_TOOL_RUBBER, 0);
5823 processKey(mapper, BTN_TOOL_PEN, 1);
5824 processSync(mapper);
5825 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5826 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005827 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005828
5829 // brush
5830 processKey(mapper, BTN_TOOL_PEN, 0);
5831 processKey(mapper, BTN_TOOL_BRUSH, 1);
5832 processSync(mapper);
5833 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5834 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005835 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005836
5837 // pencil
5838 processKey(mapper, BTN_TOOL_BRUSH, 0);
5839 processKey(mapper, BTN_TOOL_PENCIL, 1);
5840 processSync(mapper);
5841 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5842 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005843 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005844
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08005845 // air-brush
Michael Wrightd02c5b62014-02-10 15:10:22 -08005846 processKey(mapper, BTN_TOOL_PENCIL, 0);
5847 processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
5848 processSync(mapper);
5849 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5850 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005851 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005852
5853 // mouse
5854 processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
5855 processKey(mapper, BTN_TOOL_MOUSE, 1);
5856 processSync(mapper);
5857 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5858 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005859 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005860
5861 // lens
5862 processKey(mapper, BTN_TOOL_MOUSE, 0);
5863 processKey(mapper, BTN_TOOL_LENS, 1);
5864 processSync(mapper);
5865 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5866 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005867 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005868
5869 // double-tap
5870 processKey(mapper, BTN_TOOL_LENS, 0);
5871 processKey(mapper, BTN_TOOL_DOUBLETAP, 1);
5872 processSync(mapper);
5873 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5874 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005875 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005876
5877 // triple-tap
5878 processKey(mapper, BTN_TOOL_DOUBLETAP, 0);
5879 processKey(mapper, BTN_TOOL_TRIPLETAP, 1);
5880 processSync(mapper);
5881 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5882 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005883 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005884
5885 // quad-tap
5886 processKey(mapper, BTN_TOOL_TRIPLETAP, 0);
5887 processKey(mapper, BTN_TOOL_QUADTAP, 1);
5888 processSync(mapper);
5889 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5890 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005891 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005892
5893 // finger
5894 processKey(mapper, BTN_TOOL_QUADTAP, 0);
5895 processKey(mapper, BTN_TOOL_FINGER, 1);
5896 processSync(mapper);
5897 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5898 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005899 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005900
5901 // stylus trumps finger
5902 processKey(mapper, BTN_TOOL_PEN, 1);
5903 processSync(mapper);
5904 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5905 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005906 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005907
5908 // eraser trumps stylus
5909 processKey(mapper, BTN_TOOL_RUBBER, 1);
5910 processSync(mapper);
5911 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5912 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005913 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005914
5915 // mouse trumps eraser
5916 processKey(mapper, BTN_TOOL_MOUSE, 1);
5917 processSync(mapper);
5918 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5919 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005920 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005921
5922 // back to default tool type
5923 processKey(mapper, BTN_TOOL_MOUSE, 0);
5924 processKey(mapper, BTN_TOOL_RUBBER, 0);
5925 processKey(mapper, BTN_TOOL_PEN, 0);
5926 processKey(mapper, BTN_TOOL_FINGER, 0);
5927 processSync(mapper);
5928 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5929 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005930 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005931}
5932
5933TEST_F(SingleTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005934 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005935 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005936 prepareButtons();
5937 prepareAxes(POSITION);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08005938 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_FINGER, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005939 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005940
5941 NotifyMotionArgs motionArgs;
5942
5943 // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0
5944 processKey(mapper, BTN_TOOL_FINGER, 1);
5945 processMove(mapper, 100, 200);
5946 processSync(mapper);
5947 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5948 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5949 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5950 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5951
5952 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5953 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5954 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5955 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5956
5957 // move a little
5958 processMove(mapper, 150, 250);
5959 processSync(mapper);
5960 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5961 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5962 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5963 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5964
5965 // down when BTN_TOUCH is pressed, pressure defaults to 1
5966 processKey(mapper, BTN_TOUCH, 1);
5967 processSync(mapper);
5968 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5969 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5970 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5971 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5972
5973 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5974 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5975 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5976 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5977
5978 // up when BTN_TOUCH is released, hover restored
5979 processKey(mapper, BTN_TOUCH, 0);
5980 processSync(mapper);
5981 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5982 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5983 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5984 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5985
5986 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5987 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5988 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5989 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5990
5991 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5992 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5993 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5994 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5995
5996 // exit hover when pointer goes away
5997 processKey(mapper, BTN_TOOL_FINGER, 0);
5998 processSync(mapper);
5999 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6000 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
6001 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6002 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6003}
6004
6005TEST_F(SingleTouchInputMapperTest, Process_WhenAbsPressureIsPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006006 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006007 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006008 prepareButtons();
6009 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00006010 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08006011
6012 NotifyMotionArgs motionArgs;
6013
6014 // initially hovering because pressure is 0
6015 processDown(mapper, 100, 200);
6016 processPressure(mapper, 0);
6017 processSync(mapper);
6018 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6019 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
6020 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6021 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
6022
6023 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6024 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
6025 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6026 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
6027
6028 // move a little
6029 processMove(mapper, 150, 250);
6030 processSync(mapper);
6031 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6032 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
6033 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6034 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6035
6036 // down when pressure is non-zero
6037 processPressure(mapper, RAW_PRESSURE_MAX);
6038 processSync(mapper);
6039 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6040 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
6041 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6042 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6043
6044 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6045 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6046 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6047 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
6048
6049 // up when pressure becomes 0, hover restored
6050 processPressure(mapper, 0);
6051 processSync(mapper);
6052 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6053 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
6054 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6055 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
6056
6057 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6058 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
6059 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6060 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6061
6062 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6063 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
6064 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6065 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6066
6067 // exit hover when pointer goes away
6068 processUp(mapper);
6069 processSync(mapper);
6070 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6071 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
6072 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6073 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6074}
6075
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006076TEST_F(SingleTouchInputMapperTest, Reset_CancelsOngoingGesture) {
6077 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006078 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006079 prepareButtons();
6080 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00006081 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006082
6083 // Touch down.
6084 processDown(mapper, 100, 200);
6085 processPressure(mapper, 1);
6086 processSync(mapper);
6087 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6088 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
6089
6090 // Reset the mapper. This should cancel the ongoing gesture.
6091 resetMapper(mapper, ARBITRARY_TIME);
6092 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6093 WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
6094
6095 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6096}
6097
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006098TEST_F(SingleTouchInputMapperTest, Reset_RecreatesTouchState) {
6099 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006100 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006101 prepareButtons();
6102 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00006103 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006104
6105 // Set the initial state for the touch pointer.
6106 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_X, 100);
6107 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_Y, 200);
6108 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_PRESSURE, RAW_PRESSURE_MAX);
6109 mFakeEventHub->setScanCodeState(EVENTHUB_ID, BTN_TOUCH, 1);
6110
6111 // Reset the mapper. When the mapper is reset, we expect it to attempt to recreate the touch
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006112 // state by reading the current axis values. Since there was no ongoing gesture, calling reset
6113 // does not generate any events.
6114 resetMapper(mapper, ARBITRARY_TIME);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006115
6116 // Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
6117 // the recreated touch state to generate a down event.
6118 processSync(mapper);
6119 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6120 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPressure(1.f))));
6121
6122 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6123}
6124
lilinnan687e58f2022-07-19 16:00:50 +08006125TEST_F(SingleTouchInputMapperTest,
6126 Process_WhenViewportDisplayIdChanged_TouchIsCanceledAndDeviceIsReset) {
6127 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006128 prepareDisplay(ui::ROTATION_0);
lilinnan687e58f2022-07-19 16:00:50 +08006129 prepareButtons();
6130 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006131 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
lilinnan687e58f2022-07-19 16:00:50 +08006132 NotifyMotionArgs motionArgs;
6133
6134 // Down.
Prabir Pradhan3e5ec702022-07-29 16:26:24 +00006135 processDown(mapper, 100, 200);
lilinnan687e58f2022-07-19 16:00:50 +08006136 processSync(mapper);
6137
6138 // We should receive a down event
6139 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6140 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6141
6142 // Change display id
6143 clearViewports();
6144 prepareSecondaryDisplay(ViewportType::INTERNAL);
6145
6146 // We should receive a cancel event
6147 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6148 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
6149 // Then receive reset called
6150 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6151}
6152
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006153TEST_F(SingleTouchInputMapperTest,
6154 Process_WhenViewportActiveStatusChanged_TouchIsCanceledAndDeviceIsReset) {
6155 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006156 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006157 prepareButtons();
6158 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006159 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006160 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6161 NotifyMotionArgs motionArgs;
6162
6163 // Start a new gesture.
6164 processDown(mapper, 100, 200);
6165 processSync(mapper);
6166 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6167 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6168
6169 // Make the viewport inactive. This will put the device in disabled mode.
6170 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6171 viewport->isActive = false;
6172 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006173 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006174
6175 // We should receive a cancel event for the ongoing gesture.
6176 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6177 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
6178 // Then we should be notified that the device was reset.
6179 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6180
6181 // No events are generated while the viewport is inactive.
6182 processMove(mapper, 101, 201);
6183 processSync(mapper);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006184 processUp(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006185 processSync(mapper);
6186 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6187
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006188 // Start a new gesture while the viewport is still inactive.
6189 processDown(mapper, 300, 400);
6190 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_X, 300);
6191 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_Y, 400);
6192 mFakeEventHub->setScanCodeState(EVENTHUB_ID, BTN_TOUCH, 1);
6193 processSync(mapper);
6194
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006195 // Make the viewport active again. The device should resume processing events.
6196 viewport->isActive = true;
6197 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006198 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006199
6200 // The device is reset because it changes back to direct mode, without generating any events.
6201 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6202 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6203
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006204 // In the next sync, the touch state that was recreated when the device was reset is reported.
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006205 processSync(mapper);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006206 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6207 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006208
6209 // No more events.
6210 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6211 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
6212}
6213
Prabir Pradhan211ba622022-10-31 21:09:21 +00006214TEST_F(SingleTouchInputMapperTest, ButtonIsReleasedOnTouchUp) {
6215 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006216 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan211ba622022-10-31 21:09:21 +00006217 prepareButtons();
6218 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006219 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan211ba622022-10-31 21:09:21 +00006220 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6221
6222 // Press a stylus button.
6223 processKey(mapper, BTN_STYLUS, 1);
6224 processSync(mapper);
6225
6226 // Start a touch gesture and ensure the BUTTON_PRESS event is generated.
6227 processDown(mapper, 100, 200);
6228 processSync(mapper);
6229 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6230 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6231 WithCoords(toDisplayX(100), toDisplayY(200)),
6232 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6233 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6234 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
6235 WithCoords(toDisplayX(100), toDisplayY(200)),
6236 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6237
6238 // Release the touch gesture. Ensure that the BUTTON_RELEASE event is generated even though
6239 // the button has not actually been released, since there will be no pointers through which the
6240 // button state can be reported. The event is generated at the location of the pointer before
6241 // it went up.
6242 processUp(mapper);
6243 processSync(mapper);
6244 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6245 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
6246 WithCoords(toDisplayX(100), toDisplayY(200)), WithButtonState(0))));
6247 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6248 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6249 WithCoords(toDisplayX(100), toDisplayY(200)), WithButtonState(0))));
6250}
6251
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00006252TEST_F(SingleTouchInputMapperTest, StylusButtonMotionEventsDisabled) {
6253 addConfigurationProperty("touch.deviceType", "touchScreen");
6254 prepareDisplay(ui::ROTATION_0);
6255 prepareButtons();
6256 prepareAxes(POSITION);
6257
6258 mFakePolicy->setStylusButtonMotionEventsEnabled(false);
6259
Arpit Singha8c236b2023-04-25 13:56:05 +00006260 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00006261 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6262
6263 // Press a stylus button.
6264 processKey(mapper, BTN_STYLUS, 1);
6265 processSync(mapper);
6266
6267 // Start a touch gesture and ensure that the stylus button is not reported.
6268 processDown(mapper, 100, 200);
6269 processSync(mapper);
6270 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6271 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithButtonState(0))));
6272
6273 // Release and press the stylus button again.
6274 processKey(mapper, BTN_STYLUS, 0);
6275 processSync(mapper);
6276 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6277 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
6278 processKey(mapper, BTN_STYLUS, 1);
6279 processSync(mapper);
6280 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6281 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
6282
6283 // Release the touch gesture.
6284 processUp(mapper);
6285 processSync(mapper);
6286 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6287 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
6288
6289 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6290}
6291
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006292TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsSetToTouchNavigation_setsCorrectType) {
6293 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
6294 prepareDisplay(ui::ROTATION_0);
6295 prepareButtons();
6296 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006297 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006298 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6299
Prabir Pradhan9cf8f322024-06-18 20:22:42 +00006300 ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION | AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006301}
6302
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006303TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsChangedToTouchNavigation_updatesDeviceType) {
6304 // Initialize the device without setting device source to touch navigation.
6305 addConfigurationProperty("touch.deviceType", "touchScreen");
6306 prepareDisplay(ui::ROTATION_0);
6307 prepareButtons();
6308 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006309 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006310
6311 // Ensure that the device is created as a touchscreen, not touch navigation.
6312 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
6313
6314 // Add device type association after the device was created.
6315 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
6316
6317 // Send update to the mapper.
6318 std::list<NotifyArgs> unused2 =
6319 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006320 InputReaderConfiguration::Change::DEVICE_TYPE /*changes*/);
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006321
6322 // Check whether device type update was successful.
Prabir Pradhan9cf8f322024-06-18 20:22:42 +00006323 ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION | AINPUT_SOURCE_TOUCHPAD, mDevice->getSources());
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006324}
6325
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006326TEST_F(SingleTouchInputMapperTest, HoverEventsOutsidePhysicalFrameAreIgnored) {
6327 // Initialize the device without setting device source to touch navigation.
6328 addConfigurationProperty("touch.deviceType", "touchScreen");
6329 prepareDisplay(ui::ROTATION_0);
6330 prepareButtons();
6331 prepareAxes(POSITION);
6332 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
6333
6334 // Set a physical frame in the display viewport.
6335 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6336 viewport->physicalLeft = 0;
6337 viewport->physicalTop = 0;
6338 viewport->physicalRight = DISPLAY_WIDTH / 2;
6339 viewport->physicalBottom = DISPLAY_HEIGHT / 2;
6340 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006341 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006342
Arpit Singha8c236b2023-04-25 13:56:05 +00006343 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006344
6345 // Hovering inside the physical frame produces events.
6346 processKey(mapper, BTN_TOOL_PEN, 1);
6347 processMove(mapper, RAW_X_MIN + 1, RAW_Y_MIN + 1);
6348 processSync(mapper);
6349 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6350 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)));
6351 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6352 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)));
6353
6354 // Leaving the physical frame ends the hovering gesture.
6355 processMove(mapper, RAW_X_MAX - 1, RAW_Y_MAX - 1);
6356 processSync(mapper);
6357 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6358 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT)));
6359
6360 // Moving outside the physical frame does not produce events.
6361 processMove(mapper, RAW_X_MAX - 2, RAW_Y_MAX - 2);
6362 processSync(mapper);
6363 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6364
6365 // Re-entering the physical frame produces events.
6366 processMove(mapper, RAW_X_MIN, RAW_Y_MIN);
6367 processSync(mapper);
6368 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6369 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)));
6370 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6371 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)));
6372}
6373
Prabir Pradhan5632d622021-09-06 07:57:20 -07006374// --- TouchDisplayProjectionTest ---
6375
6376class TouchDisplayProjectionTest : public SingleTouchInputMapperTest {
6377public:
6378 // The values inside DisplayViewport are expected to be pre-rotated. This updates the current
6379 // DisplayViewport to pre-rotate the values. The viewport's physical display will be set to the
6380 // rotated equivalent of the given un-rotated physical display bounds.
Prabir Pradhana9df3162022-12-05 23:57:27 +00006381 void configurePhysicalDisplay(ui::Rotation orientation, Rect naturalPhysicalDisplay,
6382 int32_t naturalDisplayWidth = DISPLAY_WIDTH,
6383 int32_t naturalDisplayHeight = DISPLAY_HEIGHT) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006384 uint32_t inverseRotationFlags;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006385 auto rotatedWidth = naturalDisplayWidth;
6386 auto rotatedHeight = naturalDisplayHeight;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006387 switch (orientation) {
Michael Wrighta9cf4192022-12-01 23:46:39 +00006388 case ui::ROTATION_90:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006389 inverseRotationFlags = ui::Transform::ROT_270;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006390 std::swap(rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006391 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006392 case ui::ROTATION_180:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006393 inverseRotationFlags = ui::Transform::ROT_180;
6394 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006395 case ui::ROTATION_270:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006396 inverseRotationFlags = ui::Transform::ROT_90;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006397 std::swap(rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006398 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006399 case ui::ROTATION_0:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006400 inverseRotationFlags = ui::Transform::ROT_0;
6401 break;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006402 }
6403
Prabir Pradhana9df3162022-12-05 23:57:27 +00006404 const ui::Transform rotation(inverseRotationFlags, rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006405 const Rect rotatedPhysicalDisplay = rotation.transform(naturalPhysicalDisplay);
6406
6407 std::optional<DisplayViewport> internalViewport =
6408 *mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6409 DisplayViewport& v = *internalViewport;
6410 v.displayId = DISPLAY_ID;
6411 v.orientation = orientation;
6412
6413 v.logicalLeft = 0;
6414 v.logicalTop = 0;
6415 v.logicalRight = 100;
6416 v.logicalBottom = 100;
6417
6418 v.physicalLeft = rotatedPhysicalDisplay.left;
6419 v.physicalTop = rotatedPhysicalDisplay.top;
6420 v.physicalRight = rotatedPhysicalDisplay.right;
6421 v.physicalBottom = rotatedPhysicalDisplay.bottom;
6422
Prabir Pradhana9df3162022-12-05 23:57:27 +00006423 v.deviceWidth = rotatedWidth;
6424 v.deviceHeight = rotatedHeight;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006425
6426 v.isActive = true;
6427 v.uniqueId = UNIQUE_ID;
6428 v.type = ViewportType::INTERNAL;
6429 mFakePolicy->updateViewport(v);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006430 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006431 }
6432
6433 void assertReceivedMove(const Point& point) {
6434 NotifyMotionArgs motionArgs;
6435 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6436 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006437 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Prabir Pradhan5632d622021-09-06 07:57:20 -07006438 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], point.x, point.y,
6439 1, 0, 0, 0, 0, 0, 0, 0));
6440 }
6441};
6442
6443TEST_F(TouchDisplayProjectionTest, IgnoresTouchesOutsidePhysicalDisplay) {
6444 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006445 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006446
6447 prepareButtons();
6448 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006449 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan5632d622021-09-06 07:57:20 -07006450
6451 NotifyMotionArgs motionArgs;
6452
6453 // Configure the DisplayViewport such that the logical display maps to a subsection of
6454 // the display panel called the physical display. Here, the physical display is bounded by the
6455 // points (10, 20) and (70, 160) inside the display space, which is of the size 400 x 800.
6456 static const Rect kPhysicalDisplay{10, 20, 70, 160};
6457 static const std::array<Point, 6> kPointsOutsidePhysicalDisplay{
6458 {{-10, -10}, {0, 0}, {5, 100}, {50, 15}, {75, 100}, {50, 165}}};
6459
Michael Wrighta9cf4192022-12-01 23:46:39 +00006460 for (auto orientation : {ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180, ui::ROTATION_270}) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006461 configurePhysicalDisplay(orientation, kPhysicalDisplay);
6462
6463 // Touches outside the physical display should be ignored, and should not generate any
6464 // events. Ensure touches at the following points that lie outside of the physical display
6465 // area do not generate any events.
6466 for (const auto& point : kPointsOutsidePhysicalDisplay) {
6467 processDown(mapper, toRawX(point.x), toRawY(point.y));
6468 processSync(mapper);
6469 processUp(mapper);
6470 processSync(mapper);
6471 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled())
6472 << "Unexpected event generated for touch outside physical display at point: "
6473 << point.x << ", " << point.y;
6474 }
6475 }
6476}
6477
6478TEST_F(TouchDisplayProjectionTest, EmitsTouchDownAfterEnteringPhysicalDisplay) {
6479 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006480 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006481
6482 prepareButtons();
6483 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006484 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan5632d622021-09-06 07:57:20 -07006485
6486 NotifyMotionArgs motionArgs;
6487
6488 // Configure the DisplayViewport such that the logical display maps to a subsection of
6489 // the display panel called the physical display. Here, the physical display is bounded by the
6490 // points (10, 20) and (70, 160) inside the display space, which is of the size 400 x 800.
6491 static const Rect kPhysicalDisplay{10, 20, 70, 160};
6492
Michael Wrighta9cf4192022-12-01 23:46:39 +00006493 for (auto orientation : {ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180, ui::ROTATION_270}) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006494 configurePhysicalDisplay(orientation, kPhysicalDisplay);
6495
6496 // Touches that start outside the physical display should be ignored until it enters the
6497 // physical display bounds, at which point it should generate a down event. Start a touch at
6498 // the point (5, 100), which is outside the physical display bounds.
6499 static const Point kOutsidePoint{5, 100};
6500 processDown(mapper, toRawX(kOutsidePoint.x), toRawY(kOutsidePoint.y));
6501 processSync(mapper);
6502 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6503
6504 // Move the touch into the physical display area. This should generate a pointer down.
6505 processMove(mapper, toRawX(11), toRawY(21));
6506 processSync(mapper);
6507 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6508 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006509 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Prabir Pradhan5632d622021-09-06 07:57:20 -07006510 ASSERT_NO_FATAL_FAILURE(
6511 assertPointerCoords(motionArgs.pointerCoords[0], 11, 21, 1, 0, 0, 0, 0, 0, 0, 0));
6512
6513 // Move the touch inside the physical display area. This should generate a pointer move.
6514 processMove(mapper, toRawX(69), toRawY(159));
6515 processSync(mapper);
6516 assertReceivedMove({69, 159});
6517
6518 // Move outside the physical display area. Since the pointer is already down, this should
6519 // now continue generating events.
6520 processMove(mapper, toRawX(kOutsidePoint.x), toRawY(kOutsidePoint.y));
6521 processSync(mapper);
6522 assertReceivedMove(kOutsidePoint);
6523
6524 // Release. This should generate a pointer up.
6525 processUp(mapper);
6526 processSync(mapper);
6527 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6528 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
6529 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], kOutsidePoint.x,
6530 kOutsidePoint.y, 1, 0, 0, 0, 0, 0, 0, 0));
6531
6532 // Ensure no more events were generated.
6533 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
6534 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6535 }
6536}
6537
Prabir Pradhana9df3162022-12-05 23:57:27 +00006538// --- TouchscreenPrecisionTests ---
6539
6540// This test suite is used to ensure that touchscreen devices are scaled and configured correctly
6541// in various orientations and with different display rotations. We configure the touchscreen to
6542// have a higher resolution than that of the display by an integer scale factor in each axis so that
6543// we can enforce that coordinates match precisely as expected.
6544class TouchscreenPrecisionTestsFixture : public TouchDisplayProjectionTest,
6545 public ::testing::WithParamInterface<ui::Rotation> {
6546public:
6547 void SetUp() override {
6548 SingleTouchInputMapperTest::SetUp();
6549
6550 // Prepare the raw axes to have twice the resolution of the display in the X axis and
6551 // four times the resolution of the display in the Y axis.
6552 prepareButtons();
6553 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, PRECISION_RAW_X_MIN, PRECISION_RAW_X_MAX,
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006554 PRECISION_RAW_X_FLAT, PRECISION_RAW_X_FUZZ,
6555 PRECISION_RAW_X_RES);
Prabir Pradhana9df3162022-12-05 23:57:27 +00006556 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, PRECISION_RAW_Y_MIN, PRECISION_RAW_Y_MAX,
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006557 PRECISION_RAW_Y_FLAT, PRECISION_RAW_Y_FUZZ,
6558 PRECISION_RAW_Y_RES);
Prabir Pradhana9df3162022-12-05 23:57:27 +00006559 }
6560
6561 static const int32_t PRECISION_RAW_X_MIN = TouchInputMapperTest::RAW_X_MIN;
6562 static const int32_t PRECISION_RAW_X_MAX = PRECISION_RAW_X_MIN + DISPLAY_WIDTH * 2 - 1;
6563 static const int32_t PRECISION_RAW_Y_MIN = TouchInputMapperTest::RAW_Y_MIN;
6564 static const int32_t PRECISION_RAW_Y_MAX = PRECISION_RAW_Y_MIN + DISPLAY_HEIGHT * 4 - 1;
6565
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006566 static const int32_t PRECISION_RAW_X_RES = 50; // units per millimeter
6567 static const int32_t PRECISION_RAW_Y_RES = 100; // units per millimeter
6568
6569 static const int32_t PRECISION_RAW_X_FLAT = 16;
6570 static const int32_t PRECISION_RAW_Y_FLAT = 32;
6571
6572 static const int32_t PRECISION_RAW_X_FUZZ = 4;
6573 static const int32_t PRECISION_RAW_Y_FUZZ = 8;
6574
Prabir Pradhana9df3162022-12-05 23:57:27 +00006575 static const std::array<Point, 4> kRawCorners;
6576};
6577
6578const std::array<Point, 4> TouchscreenPrecisionTestsFixture::kRawCorners = {{
6579 {PRECISION_RAW_X_MIN, PRECISION_RAW_Y_MIN}, // left-top
6580 {PRECISION_RAW_X_MAX, PRECISION_RAW_Y_MIN}, // right-top
6581 {PRECISION_RAW_X_MAX, PRECISION_RAW_Y_MAX}, // right-bottom
6582 {PRECISION_RAW_X_MIN, PRECISION_RAW_Y_MAX}, // left-bottom
6583}};
6584
6585// Tests for how the touchscreen is oriented relative to the natural orientation of the display.
6586// For example, if a touchscreen is configured with an orientation of 90 degrees, it is a portrait
6587// touchscreen panel that is used on a device whose natural display orientation is in landscape.
6588TEST_P(TouchscreenPrecisionTestsFixture, OrientationPrecision) {
6589 enum class Orientation {
6590 ORIENTATION_0 = ui::toRotationInt(ui::ROTATION_0),
6591 ORIENTATION_90 = ui::toRotationInt(ui::ROTATION_90),
6592 ORIENTATION_180 = ui::toRotationInt(ui::ROTATION_180),
6593 ORIENTATION_270 = ui::toRotationInt(ui::ROTATION_270),
6594 ftl_last = ORIENTATION_270,
6595 };
6596 using Orientation::ORIENTATION_0, Orientation::ORIENTATION_90, Orientation::ORIENTATION_180,
6597 Orientation::ORIENTATION_270;
6598 static const std::map<Orientation, std::array<vec2, 4> /*mappedCorners*/> kMappedCorners = {
6599 {ORIENTATION_0, {{{0, 0}, {479.5, 0}, {479.5, 799.75}, {0, 799.75}}}},
6600 {ORIENTATION_90, {{{0, 479.5}, {0, 0}, {799.75, 0}, {799.75, 479.5}}}},
6601 {ORIENTATION_180, {{{479.5, 799.75}, {0, 799.75}, {0, 0}, {479.5, 0}}}},
6602 {ORIENTATION_270, {{{799.75, 0}, {799.75, 479.5}, {0, 479.5}, {0, 0}}}},
6603 };
6604
6605 const auto touchscreenOrientation = static_cast<Orientation>(ui::toRotationInt(GetParam()));
6606
6607 // Configure the touchscreen as being installed in the one of the four different orientations
6608 // relative to the display.
6609 addConfigurationProperty("touch.deviceType", "touchScreen");
6610 addConfigurationProperty("touch.orientation", ftl::enum_string(touchscreenOrientation).c_str());
6611 prepareDisplay(ui::ROTATION_0);
6612
Arpit Singha8c236b2023-04-25 13:56:05 +00006613 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhana9df3162022-12-05 23:57:27 +00006614
6615 // If the touchscreen is installed in a rotated orientation relative to the display (i.e. in
6616 // orientations of either 90 or 270) this means the display's natural resolution will be
6617 // flipped.
6618 const bool displayRotated =
6619 touchscreenOrientation == ORIENTATION_90 || touchscreenOrientation == ORIENTATION_270;
6620 const int32_t width = displayRotated ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
6621 const int32_t height = displayRotated ? DISPLAY_WIDTH : DISPLAY_HEIGHT;
6622 const Rect physicalFrame{0, 0, width, height};
6623 configurePhysicalDisplay(ui::ROTATION_0, physicalFrame, width, height);
6624
6625 const auto& expectedPoints = kMappedCorners.at(touchscreenOrientation);
6626 const float expectedPrecisionX = displayRotated ? 4 : 2;
6627 const float expectedPrecisionY = displayRotated ? 2 : 4;
6628
6629 // Test all four corners.
6630 for (int i = 0; i < 4; i++) {
6631 const auto& raw = kRawCorners[i];
6632 processDown(mapper, raw.x, raw.y);
6633 processSync(mapper);
6634 const auto& expected = expectedPoints[i];
6635 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6636 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6637 WithCoords(expected.x, expected.y),
6638 WithPrecision(expectedPrecisionX, expectedPrecisionY))))
6639 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6640 << "with touchscreen orientation "
6641 << ftl::enum_string(touchscreenOrientation).c_str() << ", expected point ("
6642 << expected.x << ", " << expected.y << ").";
6643 processUp(mapper);
6644 processSync(mapper);
6645 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6646 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6647 WithCoords(expected.x, expected.y))));
6648 }
6649}
6650
Prabir Pradhan82687402022-12-06 01:32:53 +00006651TEST_P(TouchscreenPrecisionTestsFixture, RotationPrecisionWhenOrientationAware) {
6652 static const std::map<ui::Rotation /*rotation*/, std::array<vec2, 4> /*mappedCorners*/>
6653 kMappedCorners = {
6654 {ui::ROTATION_0, {{{0, 0}, {479.5, 0}, {479.5, 799.75}, {0, 799.75}}}},
6655 {ui::ROTATION_90, {{{0.5, 0}, {480, 0}, {480, 799.75}, {0.5, 799.75}}}},
6656 {ui::ROTATION_180, {{{0.5, 0.25}, {480, 0.25}, {480, 800}, {0.5, 800}}}},
6657 {ui::ROTATION_270, {{{0, 0.25}, {479.5, 0.25}, {479.5, 800}, {0, 800}}}},
6658 };
6659
6660 const ui::Rotation displayRotation = GetParam();
6661
6662 addConfigurationProperty("touch.deviceType", "touchScreen");
6663 prepareDisplay(displayRotation);
6664
Arpit Singha8c236b2023-04-25 13:56:05 +00006665 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan82687402022-12-06 01:32:53 +00006666
6667 const auto& expectedPoints = kMappedCorners.at(displayRotation);
6668
6669 // Test all four corners.
6670 for (int i = 0; i < 4; i++) {
6671 const auto& expected = expectedPoints[i];
6672 const auto& raw = kRawCorners[i];
6673 processDown(mapper, raw.x, raw.y);
6674 processSync(mapper);
6675 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6676 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6677 WithCoords(expected.x, expected.y), WithPrecision(2, 4))))
6678 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6679 << "with display rotation " << ui::toCString(displayRotation)
6680 << ", expected point (" << expected.x << ", " << expected.y << ").";
6681 processUp(mapper);
6682 processSync(mapper);
6683 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6684 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6685 WithCoords(expected.x, expected.y))));
6686 }
6687}
6688
Prabir Pradhan3e798762022-12-02 21:02:11 +00006689TEST_P(TouchscreenPrecisionTestsFixture, RotationPrecisionOrientationAwareInOri270) {
6690 static const std::map<ui::Rotation /*orientation*/, std::array<vec2, 4> /*mappedCorners*/>
6691 kMappedCorners = {
6692 {ui::ROTATION_0, {{{799.75, 0}, {799.75, 479.5}, {0, 479.5}, {0, 0}}}},
6693 {ui::ROTATION_90, {{{800, 0}, {800, 479.5}, {0.25, 479.5}, {0.25, 0}}}},
6694 {ui::ROTATION_180, {{{800, 0.5}, {800, 480}, {0.25, 480}, {0.25, 0.5}}}},
6695 {ui::ROTATION_270, {{{799.75, 0.5}, {799.75, 480}, {0, 480}, {0, 0.5}}}},
6696 };
6697
6698 const ui::Rotation displayRotation = GetParam();
6699
6700 addConfigurationProperty("touch.deviceType", "touchScreen");
6701 addConfigurationProperty("touch.orientation", "ORIENTATION_270");
6702
Arpit Singha8c236b2023-04-25 13:56:05 +00006703 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan3e798762022-12-02 21:02:11 +00006704
6705 // Ori 270, so width and height swapped
6706 const Rect physicalFrame{0, 0, DISPLAY_HEIGHT, DISPLAY_WIDTH};
6707 prepareDisplay(displayRotation);
6708 configurePhysicalDisplay(displayRotation, physicalFrame, DISPLAY_HEIGHT, DISPLAY_WIDTH);
6709
6710 const auto& expectedPoints = kMappedCorners.at(displayRotation);
6711
6712 // Test all four corners.
6713 for (int i = 0; i < 4; i++) {
6714 const auto& expected = expectedPoints[i];
6715 const auto& raw = kRawCorners[i];
6716 processDown(mapper, raw.x, raw.y);
6717 processSync(mapper);
6718 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6719 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6720 WithCoords(expected.x, expected.y), WithPrecision(4, 2))))
6721 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6722 << "with display rotation " << ui::toCString(displayRotation)
6723 << ", expected point (" << expected.x << ", " << expected.y << ").";
6724 processUp(mapper);
6725 processSync(mapper);
6726 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6727 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6728 WithCoords(expected.x, expected.y))));
6729 }
6730}
6731
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006732TEST_P(TouchscreenPrecisionTestsFixture, MotionRangesAreOrientedInRotatedDisplay) {
6733 const ui::Rotation displayRotation = GetParam();
6734
6735 addConfigurationProperty("touch.deviceType", "touchScreen");
6736 prepareDisplay(displayRotation);
6737
6738 __attribute__((unused)) SingleTouchInputMapper& mapper =
Arpit Singha8c236b2023-04-25 13:56:05 +00006739 constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006740
6741 const InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
6742 // MotionRanges use display pixels as their units
6743 const auto* xRange = deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHSCREEN);
6744 const auto* yRange = deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_Y, AINPUT_SOURCE_TOUCHSCREEN);
6745
6746 // The MotionRanges should be oriented in the rotated display's coordinate space
6747 const bool displayRotated =
6748 displayRotation == ui::ROTATION_90 || displayRotation == ui::ROTATION_270;
6749
6750 constexpr float MAX_X = 479.5;
6751 constexpr float MAX_Y = 799.75;
6752 EXPECT_EQ(xRange->min, 0.f);
6753 EXPECT_EQ(yRange->min, 0.f);
6754 EXPECT_EQ(xRange->max, displayRotated ? MAX_Y : MAX_X);
6755 EXPECT_EQ(yRange->max, displayRotated ? MAX_X : MAX_Y);
6756
6757 EXPECT_EQ(xRange->flat, 8.f);
6758 EXPECT_EQ(yRange->flat, 8.f);
6759
6760 EXPECT_EQ(xRange->fuzz, 2.f);
6761 EXPECT_EQ(yRange->fuzz, 2.f);
6762
6763 EXPECT_EQ(xRange->resolution, 25.f); // pixels per millimeter
6764 EXPECT_EQ(yRange->resolution, 25.f); // pixels per millimeter
6765}
6766
Prabir Pradhana9df3162022-12-05 23:57:27 +00006767// Run the precision tests for all rotations.
6768INSTANTIATE_TEST_SUITE_P(TouchscreenPrecisionTests, TouchscreenPrecisionTestsFixture,
6769 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
6770 ui::ROTATION_270),
6771 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
6772 return ftl::enum_string(testParamInfo.param);
6773 });
6774
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006775// --- ExternalStylusFusionTest ---
6776
6777class ExternalStylusFusionTest : public SingleTouchInputMapperTest {
6778public:
6779 SingleTouchInputMapper& initializeInputMapperWithExternalStylus() {
6780 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006781 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006782 prepareButtons();
6783 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006784 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006785
6786 mStylusState.when = ARBITRARY_TIME;
6787 mStylusState.pressure = 0.f;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006788 mStylusState.toolType = ToolType::STYLUS;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006789 mReader->getContext()->setExternalStylusDevices({mExternalStylusDeviceInfo});
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006790 configureDevice(InputReaderConfiguration::Change::EXTERNAL_STYLUS_PRESENCE);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006791 processExternalStylusState(mapper);
6792 return mapper;
6793 }
6794
6795 std::list<NotifyArgs> processExternalStylusState(InputMapper& mapper) {
6796 std::list<NotifyArgs> generatedArgs = mapper.updateExternalStylusState(mStylusState);
6797 for (const NotifyArgs& args : generatedArgs) {
6798 mFakeListener->notify(args);
6799 }
6800 // Loop the reader to flush the input listener queue.
6801 mReader->loopOnce();
6802 return generatedArgs;
6803 }
6804
6805protected:
6806 StylusState mStylusState{};
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006807
6808 void testStartFusedStylusGesture(SingleTouchInputMapper& mapper) {
6809 auto toolTypeSource =
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006810 AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006811
6812 // The first pointer is withheld.
6813 processDown(mapper, 100, 200);
6814 processSync(mapper);
6815 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6816 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6817 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6818
6819 // The external stylus reports pressure. The withheld finger pointer is released as a
6820 // stylus.
6821 mStylusState.pressure = 1.f;
6822 processExternalStylusState(mapper);
6823 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6824 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6825 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6826
6827 // Subsequent pointer events are not withheld.
6828 processMove(mapper, 101, 201);
6829 processSync(mapper);
6830 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6831 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6832
6833 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6834 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6835 }
6836
6837 void testSuccessfulFusionGesture(SingleTouchInputMapper& mapper) {
6838 ASSERT_NO_FATAL_FAILURE(testStartFusedStylusGesture(mapper));
6839
6840 // Releasing the touch pointer ends the gesture.
6841 processUp(mapper);
6842 processSync(mapper);
6843 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006844 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(STYLUS_FUSION_SOURCE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006845 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006846
6847 mStylusState.pressure = 0.f;
6848 processExternalStylusState(mapper);
6849 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6850 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6851 }
6852
6853 void testUnsuccessfulFusionGesture(SingleTouchInputMapper& mapper) {
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006854 // When stylus fusion is not successful, events should be reported with the original source.
6855 // In this case, it is from a touchscreen.
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006856 auto toolTypeSource =
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006857 AllOf(WithSource(AINPUT_SOURCE_TOUCHSCREEN), WithToolType(ToolType::FINGER));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006858
6859 // The first pointer is withheld when an external stylus is connected,
6860 // and a timeout is requested.
6861 processDown(mapper, 100, 200);
6862 processSync(mapper);
6863 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6864 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6865 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6866
6867 // If the timeout expires early, it is requested again.
6868 handleTimeout(mapper, ARBITRARY_TIME + 1);
6869 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6870 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6871
6872 // When the timeout expires, the withheld touch is released as a finger pointer.
6873 handleTimeout(mapper, ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT);
6874 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6875 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6876
6877 // Subsequent pointer events are not withheld.
6878 processMove(mapper, 101, 201);
6879 processSync(mapper);
6880 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6881 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6882 processUp(mapper);
6883 processSync(mapper);
6884 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6885 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP))));
6886
6887 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6888 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6889 }
6890
6891private:
6892 InputDeviceInfo mExternalStylusDeviceInfo{};
6893};
6894
6895TEST_F(ExternalStylusFusionTest, UsesBluetoothStylusSource) {
6896 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006897 ASSERT_EQ(STYLUS_FUSION_SOURCE, mapper.getSources());
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006898}
6899
6900TEST_F(ExternalStylusFusionTest, UnsuccessfulFusion) {
6901 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6902 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6903}
6904
6905TEST_F(ExternalStylusFusionTest, SuccessfulFusion_TouchFirst) {
6906 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6907 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6908}
6909
6910// Test a successful stylus fusion gesture where the pressure is reported by the external
6911// before the touch is reported by the touchscreen.
6912TEST_F(ExternalStylusFusionTest, SuccessfulFusion_PressureFirst) {
6913 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006914 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006915
6916 // The external stylus reports pressure first. It is ignored for now.
6917 mStylusState.pressure = 1.f;
6918 processExternalStylusState(mapper);
6919 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6920 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6921
6922 // When the touch goes down afterwards, it is reported as a stylus pointer.
6923 processDown(mapper, 100, 200);
6924 processSync(mapper);
6925 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6926 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6927 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6928
6929 processMove(mapper, 101, 201);
6930 processSync(mapper);
6931 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6932 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6933 processUp(mapper);
6934 processSync(mapper);
6935 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6936 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP))));
6937
6938 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6939 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6940}
6941
6942TEST_F(ExternalStylusFusionTest, FusionIsRepeatedForEachNewGesture) {
6943 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6944
6945 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6946 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6947
6948 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6949 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6950 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6951 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6952}
6953
6954TEST_F(ExternalStylusFusionTest, FusedPointerReportsPressureChanges) {
6955 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006956 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006957
6958 mStylusState.pressure = 0.8f;
6959 processExternalStylusState(mapper);
6960 processDown(mapper, 100, 200);
6961 processSync(mapper);
6962 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6963 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6964 WithPressure(0.8f))));
6965 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6966
6967 // The external stylus reports a pressure change. We wait for some time for a touch event.
6968 mStylusState.pressure = 0.6f;
6969 processExternalStylusState(mapper);
6970 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6971 ASSERT_NO_FATAL_FAILURE(
6972 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6973
6974 // If a touch is reported within the timeout, it reports the updated pressure.
6975 processMove(mapper, 101, 201);
6976 processSync(mapper);
6977 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6978 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6979 WithPressure(0.6f))));
6980 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6981
6982 // There is another pressure change.
6983 mStylusState.pressure = 0.5f;
6984 processExternalStylusState(mapper);
6985 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6986 ASSERT_NO_FATAL_FAILURE(
6987 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6988
6989 // If a touch is not reported within the timeout, a move event is generated to report
6990 // the new pressure.
6991 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
6992 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6993 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6994 WithPressure(0.5f))));
6995
6996 // If a zero pressure is reported before the touch goes up, the previous pressure value is
6997 // repeated indefinitely.
6998 mStylusState.pressure = 0.0f;
6999 processExternalStylusState(mapper);
7000 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7001 ASSERT_NO_FATAL_FAILURE(
7002 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7003 processMove(mapper, 102, 202);
7004 processSync(mapper);
7005 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7006 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
7007 WithPressure(0.5f))));
7008 processMove(mapper, 103, 203);
7009 processSync(mapper);
7010 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7011 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
7012 WithPressure(0.5f))));
7013
7014 processUp(mapper);
7015 processSync(mapper);
7016 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00007017 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(STYLUS_FUSION_SOURCE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007018 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007019
7020 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7021 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7022}
7023
7024TEST_F(ExternalStylusFusionTest, FusedPointerReportsToolTypeChanges) {
7025 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00007026 auto source = WithSource(STYLUS_FUSION_SOURCE);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007027
7028 mStylusState.pressure = 1.f;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007029 mStylusState.toolType = ToolType::ERASER;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007030 processExternalStylusState(mapper);
7031 processDown(mapper, 100, 200);
7032 processSync(mapper);
7033 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7034 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007035 WithToolType(ToolType::ERASER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007036 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7037
7038 // The external stylus reports a tool change. We wait for some time for a touch event.
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007039 mStylusState.toolType = ToolType::STYLUS;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007040 processExternalStylusState(mapper);
7041 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7042 ASSERT_NO_FATAL_FAILURE(
7043 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7044
7045 // If a touch is reported within the timeout, it reports the updated pressure.
7046 processMove(mapper, 101, 201);
7047 processSync(mapper);
7048 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7049 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007050 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007051 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7052
7053 // There is another tool type change.
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007054 mStylusState.toolType = ToolType::FINGER;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007055 processExternalStylusState(mapper);
7056 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7057 ASSERT_NO_FATAL_FAILURE(
7058 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7059
7060 // If a touch is not reported within the timeout, a move event is generated to report
7061 // the new tool type.
7062 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
7063 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7064 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007065 WithToolType(ToolType::FINGER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007066
7067 processUp(mapper);
7068 processSync(mapper);
7069 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7070 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007071 WithToolType(ToolType::FINGER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007072
7073 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7074 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7075}
7076
7077TEST_F(ExternalStylusFusionTest, FusedPointerReportsButtons) {
7078 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00007079 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007080
7081 ASSERT_NO_FATAL_FAILURE(testStartFusedStylusGesture(mapper));
7082
7083 // The external stylus reports a button change. We wait for some time for a touch event.
7084 mStylusState.buttons = AMOTION_EVENT_BUTTON_STYLUS_PRIMARY;
7085 processExternalStylusState(mapper);
7086 ASSERT_NO_FATAL_FAILURE(
7087 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7088
7089 // If a touch is reported within the timeout, it reports the updated button state.
7090 processMove(mapper, 101, 201);
7091 processSync(mapper);
7092 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7093 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
7094 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
7095 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7096 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
7097 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
7098 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7099
7100 // The button is now released.
7101 mStylusState.buttons = 0;
7102 processExternalStylusState(mapper);
7103 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7104 ASSERT_NO_FATAL_FAILURE(
7105 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7106
7107 // If a touch is not reported within the timeout, a move event is generated to report
7108 // the new button state.
7109 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007110 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7111 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
7112 WithButtonState(0))));
7113 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhan124ea442022-10-28 20:27:44 +00007114 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
7115 WithButtonState(0))));
7116
7117 processUp(mapper);
7118 processSync(mapper);
7119 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007120 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
7121
7122 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7123 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7124}
7125
Michael Wrightd02c5b62014-02-10 15:10:22 -08007126// --- MultiTouchInputMapperTest ---
7127
7128class MultiTouchInputMapperTest : public TouchInputMapperTest {
7129protected:
7130 void prepareAxes(int axes);
7131
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007132 void processPosition(MultiTouchInputMapper& mapper, int32_t x, int32_t y);
7133 void processTouchMajor(MultiTouchInputMapper& mapper, int32_t touchMajor);
7134 void processTouchMinor(MultiTouchInputMapper& mapper, int32_t touchMinor);
7135 void processToolMajor(MultiTouchInputMapper& mapper, int32_t toolMajor);
7136 void processToolMinor(MultiTouchInputMapper& mapper, int32_t toolMinor);
7137 void processOrientation(MultiTouchInputMapper& mapper, int32_t orientation);
7138 void processPressure(MultiTouchInputMapper& mapper, int32_t pressure);
7139 void processDistance(MultiTouchInputMapper& mapper, int32_t distance);
7140 void processId(MultiTouchInputMapper& mapper, int32_t id);
7141 void processSlot(MultiTouchInputMapper& mapper, int32_t slot);
7142 void processToolType(MultiTouchInputMapper& mapper, int32_t toolType);
7143 void processKey(MultiTouchInputMapper& mapper, int32_t code, int32_t value);
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00007144 void processHidUsage(MultiTouchInputMapper& mapper, int32_t usageCode, int32_t value);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007145 void processMTSync(MultiTouchInputMapper& mapper);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00007146 void processSync(MultiTouchInputMapper& mapper, nsecs_t eventTime = ARBITRARY_TIME,
7147 nsecs_t readTime = READ_TIME);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007148};
7149
7150void MultiTouchInputMapperTest::prepareAxes(int axes) {
7151 if (axes & POSITION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007152 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
7153 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007154 }
7155 if (axes & TOUCH) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007156 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN,
7157 RAW_TOUCH_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007158 if (axes & MINOR) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007159 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN,
7160 RAW_TOUCH_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007161 }
7162 }
7163 if (axes & TOOL) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007164 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7165 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007166 if (axes & MINOR) {
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007167 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MIN,
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007168 RAW_TOOL_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007169 }
7170 }
7171 if (axes & ORIENTATION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007172 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_ORIENTATION, RAW_ORIENTATION_MIN,
7173 RAW_ORIENTATION_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007174 }
7175 if (axes & PRESSURE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007176 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_PRESSURE, RAW_PRESSURE_MIN,
7177 RAW_PRESSURE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007178 }
7179 if (axes & DISTANCE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007180 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_DISTANCE, RAW_DISTANCE_MIN,
7181 RAW_DISTANCE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007182 }
7183 if (axes & ID) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007184 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TRACKING_ID, RAW_ID_MIN, RAW_ID_MAX, 0,
7185 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007186 }
7187 if (axes & SLOT) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007188 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_SLOT, RAW_SLOT_MIN, RAW_SLOT_MAX, 0, 0);
7189 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007190 }
7191 if (axes & TOOL_TYPE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007192 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007193 }
7194}
7195
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007196void MultiTouchInputMapperTest::processPosition(MultiTouchInputMapper& mapper, int32_t x,
7197 int32_t y) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007198 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
7199 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007200}
7201
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007202void MultiTouchInputMapperTest::processTouchMajor(MultiTouchInputMapper& mapper,
7203 int32_t touchMajor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007204 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOUCH_MAJOR, touchMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007205}
7206
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007207void MultiTouchInputMapperTest::processTouchMinor(MultiTouchInputMapper& mapper,
7208 int32_t touchMinor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007209 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOUCH_MINOR, touchMinor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007210}
7211
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007212void MultiTouchInputMapperTest::processToolMajor(MultiTouchInputMapper& mapper, int32_t toolMajor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007213 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_WIDTH_MAJOR, toolMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007214}
7215
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007216void MultiTouchInputMapperTest::processToolMinor(MultiTouchInputMapper& mapper, int32_t toolMinor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007217 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_WIDTH_MINOR, toolMinor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007218}
7219
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007220void MultiTouchInputMapperTest::processOrientation(MultiTouchInputMapper& mapper,
7221 int32_t orientation) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007222 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_ORIENTATION, orientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007223}
7224
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007225void MultiTouchInputMapperTest::processPressure(MultiTouchInputMapper& mapper, int32_t pressure) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007226 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_PRESSURE, pressure);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007227}
7228
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007229void MultiTouchInputMapperTest::processDistance(MultiTouchInputMapper& mapper, int32_t distance) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007230 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_DISTANCE, distance);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007231}
7232
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007233void MultiTouchInputMapperTest::processId(MultiTouchInputMapper& mapper, int32_t id) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007234 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TRACKING_ID, id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007235}
7236
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007237void MultiTouchInputMapperTest::processSlot(MultiTouchInputMapper& mapper, int32_t slot) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007238 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_SLOT, slot);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007239}
7240
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007241void MultiTouchInputMapperTest::processToolType(MultiTouchInputMapper& mapper, int32_t toolType) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007242 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOOL_TYPE, toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007243}
7244
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007245void MultiTouchInputMapperTest::processKey(MultiTouchInputMapper& mapper, int32_t code,
7246 int32_t value) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007247 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007248}
7249
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00007250void MultiTouchInputMapperTest::processHidUsage(MultiTouchInputMapper& mapper, int32_t usageCode,
7251 int32_t value) {
7252 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, usageCode);
7253 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, value);
7254}
7255
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007256void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper& mapper) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007257 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_MT_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007258}
7259
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00007260void MultiTouchInputMapperTest::processSync(MultiTouchInputMapper& mapper, nsecs_t eventTime,
7261 nsecs_t readTime) {
7262 process(mapper, eventTime, readTime, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007263}
7264
Michael Wrightd02c5b62014-02-10 15:10:22 -08007265TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackingIds) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007266 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007267 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007268 prepareAxes(POSITION);
7269 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007270 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007271
arthurhungdcef2dc2020-08-11 14:47:50 +08007272 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007273
7274 NotifyMotionArgs motionArgs;
7275
7276 // Two fingers down at once.
7277 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7278 processPosition(mapper, x1, y1);
7279 processMTSync(mapper);
7280 processPosition(mapper, x2, y2);
7281 processMTSync(mapper);
7282 processSync(mapper);
7283
7284 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7285 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7286 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7287 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7288 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7289 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
7290 ASSERT_EQ(0, motionArgs.flags);
7291 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7292 ASSERT_EQ(0, motionArgs.buttonState);
7293 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007294 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007295 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007296 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007297 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7298 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7299 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7300 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7301 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7302
7303 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7304 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7305 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7306 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7307 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007308 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007309 ASSERT_EQ(0, motionArgs.flags);
7310 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7311 ASSERT_EQ(0, motionArgs.buttonState);
7312 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007313 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007314 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007315 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007316 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007317 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007318 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7319 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7320 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7321 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7322 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7323 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7324 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7325
7326 // Move.
7327 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7328 processPosition(mapper, x1, y1);
7329 processMTSync(mapper);
7330 processPosition(mapper, x2, y2);
7331 processMTSync(mapper);
7332 processSync(mapper);
7333
7334 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7335 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7336 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7337 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7338 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7339 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7340 ASSERT_EQ(0, motionArgs.flags);
7341 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7342 ASSERT_EQ(0, motionArgs.buttonState);
7343 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007344 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007345 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007346 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007347 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007348 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007349 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7350 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7351 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7352 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7353 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7354 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7355 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7356
7357 // First finger up.
7358 x2 += 15; y2 -= 20;
7359 processPosition(mapper, x2, y2);
7360 processMTSync(mapper);
7361 processSync(mapper);
7362
7363 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7364 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7365 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7366 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7367 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007368 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007369 ASSERT_EQ(0, motionArgs.flags);
7370 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7371 ASSERT_EQ(0, motionArgs.buttonState);
7372 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007373 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007374 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007375 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007376 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007377 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007378 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7379 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7380 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7381 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7382 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7383 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7384 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7385
7386 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7387 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7388 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7389 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7390 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7391 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7392 ASSERT_EQ(0, motionArgs.flags);
7393 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7394 ASSERT_EQ(0, motionArgs.buttonState);
7395 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007396 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007397 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007398 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007399 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7400 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7401 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7402 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7403 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7404
7405 // Move.
7406 x2 += 20; y2 -= 25;
7407 processPosition(mapper, x2, y2);
7408 processMTSync(mapper);
7409 processSync(mapper);
7410
7411 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7412 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7413 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7414 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7415 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7416 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7417 ASSERT_EQ(0, motionArgs.flags);
7418 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7419 ASSERT_EQ(0, motionArgs.buttonState);
7420 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007421 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007422 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007423 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007424 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7425 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7426 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7427 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7428 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7429
7430 // New finger down.
7431 int32_t x3 = 700, y3 = 300;
7432 processPosition(mapper, x2, y2);
7433 processMTSync(mapper);
7434 processPosition(mapper, x3, y3);
7435 processMTSync(mapper);
7436 processSync(mapper);
7437
7438 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7439 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7440 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7441 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7442 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007443 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007444 ASSERT_EQ(0, motionArgs.flags);
7445 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7446 ASSERT_EQ(0, motionArgs.buttonState);
7447 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007448 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007449 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007450 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007451 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007452 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007453 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7454 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7455 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7456 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7457 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7458 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7459 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7460
7461 // Second finger up.
7462 x3 += 30; y3 -= 20;
7463 processPosition(mapper, x3, y3);
7464 processMTSync(mapper);
7465 processSync(mapper);
7466
7467 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7468 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7469 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7470 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7471 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007472 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007473 ASSERT_EQ(0, motionArgs.flags);
7474 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7475 ASSERT_EQ(0, motionArgs.buttonState);
7476 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007477 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007478 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007479 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007480 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007481 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007482 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7483 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7484 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7485 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7486 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7487 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7488 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7489
7490 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7491 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7492 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7493 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7494 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7495 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7496 ASSERT_EQ(0, motionArgs.flags);
7497 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7498 ASSERT_EQ(0, motionArgs.buttonState);
7499 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007500 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007501 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007502 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007503 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7504 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7505 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7506 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7507 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7508
7509 // Last finger up.
7510 processMTSync(mapper);
7511 processSync(mapper);
7512
7513 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7514 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7515 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7516 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7517 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7518 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
7519 ASSERT_EQ(0, motionArgs.flags);
7520 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7521 ASSERT_EQ(0, motionArgs.buttonState);
7522 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007523 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007524 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007525 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007526 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7527 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7528 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7529 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7530 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7531
7532 // Should not have sent any more keys or motions.
7533 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7534 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7535}
7536
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007537TEST_F(MultiTouchInputMapperTest, AxisResolution_IsPopulated) {
7538 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007539 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007540
7541 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, /*flat*/ 0,
7542 /*fuzz*/ 0, /*resolution*/ 10);
7543 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, /*flat*/ 0,
7544 /*fuzz*/ 0, /*resolution*/ 11);
7545 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX,
7546 /*flat*/ 0, /*fuzz*/ 0, /*resolution*/ 12);
7547 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX,
7548 /*flat*/ 0, /*fuzz*/ 0, /*resolution*/ 13);
7549 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7550 /*flat*/ 0, /*flat*/ 0, /*resolution*/ 14);
7551 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7552 /*flat*/ 0, /*flat*/ 0, /*resolution*/ 15);
7553
Arpit Singha8c236b2023-04-25 13:56:05 +00007554 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007555
7556 // X and Y axes
7557 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_X, 10 / X_PRECISION);
7558 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_Y, 11 / Y_PRECISION);
7559 // Touch major and minor
7560 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOUCH_MAJOR, 12 * GEOMETRIC_SCALE);
7561 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOUCH_MINOR, 13 * GEOMETRIC_SCALE);
7562 // Tool major and minor
7563 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOOL_MAJOR, 14 * GEOMETRIC_SCALE);
7564 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOOL_MINOR, 15 * GEOMETRIC_SCALE);
7565}
7566
7567TEST_F(MultiTouchInputMapperTest, TouchMajorAndMinorAxes_DoNotAppearIfNotSupported) {
7568 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007569 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007570
7571 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, /*flat*/ 0,
7572 /*fuzz*/ 0, /*resolution*/ 10);
7573 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, /*flat*/ 0,
7574 /*fuzz*/ 0, /*resolution*/ 11);
7575
7576 // We do not add ABS_MT_TOUCH_MAJOR / MINOR or ABS_MT_WIDTH_MAJOR / MINOR axes
7577
Arpit Singha8c236b2023-04-25 13:56:05 +00007578 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007579
7580 // Touch major and minor
7581 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOUCH_MAJOR);
7582 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOUCH_MINOR);
7583 // Tool major and minor
7584 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOOL_MAJOR);
7585 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOOL_MINOR);
7586}
7587
Michael Wrightd02c5b62014-02-10 15:10:22 -08007588TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingIds) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007589 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007590 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007591 prepareAxes(POSITION | ID);
7592 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007593 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007594
arthurhungdcef2dc2020-08-11 14:47:50 +08007595 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007596
7597 NotifyMotionArgs motionArgs;
7598
7599 // Two fingers down at once.
7600 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7601 processPosition(mapper, x1, y1);
7602 processId(mapper, 1);
7603 processMTSync(mapper);
7604 processPosition(mapper, x2, y2);
7605 processId(mapper, 2);
7606 processMTSync(mapper);
7607 processSync(mapper);
7608
7609 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7610 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007611 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007612 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007613 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007614 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7615 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7616
7617 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007618 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007619 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007620 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007621 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007622 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007623 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007624 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7625 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7626 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7627 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7628
7629 // Move.
7630 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7631 processPosition(mapper, x1, y1);
7632 processId(mapper, 1);
7633 processMTSync(mapper);
7634 processPosition(mapper, x2, y2);
7635 processId(mapper, 2);
7636 processMTSync(mapper);
7637 processSync(mapper);
7638
7639 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7640 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007641 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007642 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007643 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007644 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007645 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007646 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7647 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7648 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7649 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7650
7651 // First finger up.
7652 x2 += 15; y2 -= 20;
7653 processPosition(mapper, x2, y2);
7654 processId(mapper, 2);
7655 processMTSync(mapper);
7656 processSync(mapper);
7657
7658 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007659 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007660 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007661 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007662 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007663 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007664 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007665 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7666 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7667 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7668 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7669
7670 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7671 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007672 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007673 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007674 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007675 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7676 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7677
7678 // Move.
7679 x2 += 20; y2 -= 25;
7680 processPosition(mapper, x2, y2);
7681 processId(mapper, 2);
7682 processMTSync(mapper);
7683 processSync(mapper);
7684
7685 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7686 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007687 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007688 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007689 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007690 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7691 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7692
7693 // New finger down.
7694 int32_t x3 = 700, y3 = 300;
7695 processPosition(mapper, x2, y2);
7696 processId(mapper, 2);
7697 processMTSync(mapper);
7698 processPosition(mapper, x3, y3);
7699 processId(mapper, 3);
7700 processMTSync(mapper);
7701 processSync(mapper);
7702
7703 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007704 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007705 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007706 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007707 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007708 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007709 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007710 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7711 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7712 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7713 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7714
7715 // Second finger up.
7716 x3 += 30; y3 -= 20;
7717 processPosition(mapper, x3, y3);
7718 processId(mapper, 3);
7719 processMTSync(mapper);
7720 processSync(mapper);
7721
7722 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007723 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007724 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007725 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007726 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007727 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007728 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007729 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7730 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7731 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7732 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7733
7734 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7735 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007736 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007737 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007738 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007739 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7740 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7741
7742 // Last finger up.
7743 processMTSync(mapper);
7744 processSync(mapper);
7745
7746 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7747 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007748 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007749 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007750 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007751 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7752 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7753
7754 // Should not have sent any more keys or motions.
7755 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7756 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7757}
7758
7759TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithSlots) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007760 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007761 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007762 prepareAxes(POSITION | ID | SLOT);
7763 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007764 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007765
arthurhungdcef2dc2020-08-11 14:47:50 +08007766 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007767
7768 NotifyMotionArgs motionArgs;
7769
7770 // Two fingers down at once.
7771 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7772 processPosition(mapper, x1, y1);
7773 processId(mapper, 1);
7774 processSlot(mapper, 1);
7775 processPosition(mapper, x2, y2);
7776 processId(mapper, 2);
7777 processSync(mapper);
7778
7779 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7780 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007781 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007782 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007783 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007784 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7785 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7786
7787 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007788 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007789 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007790 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007791 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007792 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007793 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007794 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7795 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7796 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7797 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7798
7799 // Move.
7800 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7801 processSlot(mapper, 0);
7802 processPosition(mapper, x1, y1);
7803 processSlot(mapper, 1);
7804 processPosition(mapper, x2, y2);
7805 processSync(mapper);
7806
7807 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7808 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007809 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007810 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007811 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007812 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007813 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007814 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7815 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7816 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7817 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7818
7819 // First finger up.
7820 x2 += 15; y2 -= 20;
7821 processSlot(mapper, 0);
7822 processId(mapper, -1);
7823 processSlot(mapper, 1);
7824 processPosition(mapper, x2, y2);
7825 processSync(mapper);
7826
7827 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007828 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007829 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007830 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007831 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007832 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007833 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007834 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7835 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7836 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7837 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7838
7839 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7840 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007841 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007842 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007843 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007844 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7845 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7846
7847 // Move.
7848 x2 += 20; y2 -= 25;
7849 processPosition(mapper, x2, y2);
7850 processSync(mapper);
7851
7852 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7853 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007854 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007855 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007856 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007857 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7858 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7859
7860 // New finger down.
7861 int32_t x3 = 700, y3 = 300;
7862 processPosition(mapper, x2, y2);
7863 processSlot(mapper, 0);
7864 processId(mapper, 3);
7865 processPosition(mapper, x3, y3);
7866 processSync(mapper);
7867
7868 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007869 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007870 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007871 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007872 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007873 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007874 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007875 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7876 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7877 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7878 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7879
7880 // Second finger up.
7881 x3 += 30; y3 -= 20;
7882 processSlot(mapper, 1);
7883 processId(mapper, -1);
7884 processSlot(mapper, 0);
7885 processPosition(mapper, x3, y3);
7886 processSync(mapper);
7887
7888 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007889 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007890 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007891 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007892 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007893 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007894 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007895 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7896 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7897 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7898 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7899
7900 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7901 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007902 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007903 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007904 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007905 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7906 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7907
7908 // Last finger up.
7909 processId(mapper, -1);
7910 processSync(mapper);
7911
7912 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7913 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007914 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007915 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007916 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007917 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7918 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7919
7920 // Should not have sent any more keys or motions.
7921 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7922 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7923}
7924
7925TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007926 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007927 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007928 prepareAxes(POSITION | TOUCH | TOOL | PRESSURE | ORIENTATION | ID | MINOR | DISTANCE);
Arpit Singha8c236b2023-04-25 13:56:05 +00007929 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007930
7931 // These calculations are based on the input device calibration documentation.
7932 int32_t rawX = 100;
7933 int32_t rawY = 200;
7934 int32_t rawTouchMajor = 7;
7935 int32_t rawTouchMinor = 6;
7936 int32_t rawToolMajor = 9;
7937 int32_t rawToolMinor = 8;
7938 int32_t rawPressure = 11;
7939 int32_t rawDistance = 0;
7940 int32_t rawOrientation = 3;
7941 int32_t id = 5;
7942
7943 float x = toDisplayX(rawX);
7944 float y = toDisplayY(rawY);
7945 float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
7946 float size = avg(rawTouchMajor, rawTouchMinor) / RAW_TOUCH_MAX;
7947 float toolMajor = float(rawToolMajor) * GEOMETRIC_SCALE;
7948 float toolMinor = float(rawToolMinor) * GEOMETRIC_SCALE;
7949 float touchMajor = float(rawTouchMajor) * GEOMETRIC_SCALE;
7950 float touchMinor = float(rawTouchMinor) * GEOMETRIC_SCALE;
7951 float orientation = float(rawOrientation) / RAW_ORIENTATION_MAX * M_PI_2;
7952 float distance = float(rawDistance);
7953
7954 processPosition(mapper, rawX, rawY);
7955 processTouchMajor(mapper, rawTouchMajor);
7956 processTouchMinor(mapper, rawTouchMinor);
7957 processToolMajor(mapper, rawToolMajor);
7958 processToolMinor(mapper, rawToolMinor);
7959 processPressure(mapper, rawPressure);
7960 processOrientation(mapper, rawOrientation);
7961 processDistance(mapper, rawDistance);
7962 processId(mapper, id);
7963 processMTSync(mapper);
7964 processSync(mapper);
7965
7966 NotifyMotionArgs args;
7967 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7968 ASSERT_EQ(0, args.pointerProperties[0].id);
7969 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7970 x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor,
7971 orientation, distance));
Prabir Pradhan9a53b552024-06-04 02:59:40 +00007972 ASSERT_EQ(args.flags, AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007973}
7974
7975TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_GeometricCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007976 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007977 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007978 prepareAxes(POSITION | TOUCH | TOOL | MINOR);
7979 addConfigurationProperty("touch.size.calibration", "geometric");
Arpit Singha8c236b2023-04-25 13:56:05 +00007980 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007981
7982 // These calculations are based on the input device calibration documentation.
7983 int32_t rawX = 100;
7984 int32_t rawY = 200;
7985 int32_t rawTouchMajor = 140;
7986 int32_t rawTouchMinor = 120;
7987 int32_t rawToolMajor = 180;
7988 int32_t rawToolMinor = 160;
7989
7990 float x = toDisplayX(rawX);
7991 float y = toDisplayY(rawY);
7992 float size = avg(rawTouchMajor, rawTouchMinor) / RAW_TOUCH_MAX;
7993 float toolMajor = float(rawToolMajor) * GEOMETRIC_SCALE;
7994 float toolMinor = float(rawToolMinor) * GEOMETRIC_SCALE;
7995 float touchMajor = float(rawTouchMajor) * GEOMETRIC_SCALE;
7996 float touchMinor = float(rawTouchMinor) * GEOMETRIC_SCALE;
7997
7998 processPosition(mapper, rawX, rawY);
7999 processTouchMajor(mapper, rawTouchMajor);
8000 processTouchMinor(mapper, rawTouchMinor);
8001 processToolMajor(mapper, rawToolMajor);
8002 processToolMinor(mapper, rawToolMinor);
8003 processMTSync(mapper);
8004 processSync(mapper);
8005
8006 NotifyMotionArgs args;
8007 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8008 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8009 x, y, 1.0f, size, touchMajor, touchMinor, toolMajor, toolMinor, 0, 0));
8010}
8011
8012TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_SummedLinearCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008013 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008014 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008015 prepareAxes(POSITION | TOUCH | TOOL);
8016 addConfigurationProperty("touch.size.calibration", "diameter");
8017 addConfigurationProperty("touch.size.scale", "10");
8018 addConfigurationProperty("touch.size.bias", "160");
8019 addConfigurationProperty("touch.size.isSummed", "1");
Arpit Singha8c236b2023-04-25 13:56:05 +00008020 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008021
8022 // These calculations are based on the input device calibration documentation.
8023 // Note: We only provide a single common touch/tool value because the device is assumed
8024 // not to emit separate values for each pointer (isSummed = 1).
8025 int32_t rawX = 100;
8026 int32_t rawY = 200;
8027 int32_t rawX2 = 150;
8028 int32_t rawY2 = 250;
8029 int32_t rawTouchMajor = 5;
8030 int32_t rawToolMajor = 8;
8031
8032 float x = toDisplayX(rawX);
8033 float y = toDisplayY(rawY);
8034 float x2 = toDisplayX(rawX2);
8035 float y2 = toDisplayY(rawY2);
8036 float size = float(rawTouchMajor) / 2 / RAW_TOUCH_MAX;
8037 float touch = float(rawTouchMajor) / 2 * 10.0f + 160.0f;
8038 float tool = float(rawToolMajor) / 2 * 10.0f + 160.0f;
8039
8040 processPosition(mapper, rawX, rawY);
8041 processTouchMajor(mapper, rawTouchMajor);
8042 processToolMajor(mapper, rawToolMajor);
8043 processMTSync(mapper);
8044 processPosition(mapper, rawX2, rawY2);
8045 processTouchMajor(mapper, rawTouchMajor);
8046 processToolMajor(mapper, rawToolMajor);
8047 processMTSync(mapper);
8048 processSync(mapper);
8049
8050 NotifyMotionArgs args;
8051 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8052 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
8053
8054 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08008055 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07008056 ASSERT_EQ(size_t(2), args.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08008057 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8058 x, y, 1.0f, size, touch, touch, tool, tool, 0, 0));
8059 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[1],
8060 x2, y2, 1.0f, size, touch, touch, tool, tool, 0, 0));
8061}
8062
8063TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_AreaCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008064 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008065 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008066 prepareAxes(POSITION | TOUCH | TOOL);
8067 addConfigurationProperty("touch.size.calibration", "area");
8068 addConfigurationProperty("touch.size.scale", "43");
8069 addConfigurationProperty("touch.size.bias", "3");
Arpit Singha8c236b2023-04-25 13:56:05 +00008070 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008071
8072 // These calculations are based on the input device calibration documentation.
8073 int32_t rawX = 100;
8074 int32_t rawY = 200;
8075 int32_t rawTouchMajor = 5;
8076 int32_t rawToolMajor = 8;
8077
8078 float x = toDisplayX(rawX);
8079 float y = toDisplayY(rawY);
8080 float size = float(rawTouchMajor) / RAW_TOUCH_MAX;
8081 float touch = sqrtf(rawTouchMajor) * 43.0f + 3.0f;
8082 float tool = sqrtf(rawToolMajor) * 43.0f + 3.0f;
8083
8084 processPosition(mapper, rawX, rawY);
8085 processTouchMajor(mapper, rawTouchMajor);
8086 processToolMajor(mapper, rawToolMajor);
8087 processMTSync(mapper);
8088 processSync(mapper);
8089
8090 NotifyMotionArgs args;
8091 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8092 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8093 x, y, 1.0f, size, touch, touch, tool, tool, 0, 0));
8094}
8095
8096TEST_F(MultiTouchInputMapperTest, Process_PressureAxis_AmplitudeCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008097 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008098 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008099 prepareAxes(POSITION | PRESSURE);
8100 addConfigurationProperty("touch.pressure.calibration", "amplitude");
8101 addConfigurationProperty("touch.pressure.scale", "0.01");
Arpit Singha8c236b2023-04-25 13:56:05 +00008102 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008103
Michael Wrightaa449c92017-12-13 21:21:43 +00008104 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +00008105 mapper.populateDeviceInfo(info);
Michael Wrightaa449c92017-12-13 21:21:43 +00008106 ASSERT_NO_FATAL_FAILURE(assertMotionRange(info,
8107 AINPUT_MOTION_RANGE_PRESSURE, AINPUT_SOURCE_TOUCHSCREEN,
8108 0.0f, RAW_PRESSURE_MAX * 0.01, 0.0f, 0.0f));
8109
Michael Wrightd02c5b62014-02-10 15:10:22 -08008110 // These calculations are based on the input device calibration documentation.
8111 int32_t rawX = 100;
8112 int32_t rawY = 200;
8113 int32_t rawPressure = 60;
8114
8115 float x = toDisplayX(rawX);
8116 float y = toDisplayY(rawY);
8117 float pressure = float(rawPressure) * 0.01f;
8118
8119 processPosition(mapper, rawX, rawY);
8120 processPressure(mapper, rawPressure);
8121 processMTSync(mapper);
8122 processSync(mapper);
8123
8124 NotifyMotionArgs args;
8125 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8126 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8127 x, y, pressure, 0, 0, 0, 0, 0, 0, 0));
8128}
8129
8130TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllButtons) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008131 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008132 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008133 prepareAxes(POSITION | ID | SLOT);
Arpit Singha8c236b2023-04-25 13:56:05 +00008134 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008135
8136 NotifyMotionArgs motionArgs;
8137 NotifyKeyArgs keyArgs;
8138
8139 processId(mapper, 1);
8140 processPosition(mapper, 100, 200);
8141 processSync(mapper);
8142 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8143 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8144 ASSERT_EQ(0, motionArgs.buttonState);
8145
8146 // press BTN_LEFT, release BTN_LEFT
8147 processKey(mapper, BTN_LEFT, 1);
8148 processSync(mapper);
8149 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8150 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
8151 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
8152
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008153 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8154 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8155 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
8156
Michael Wrightd02c5b62014-02-10 15:10:22 -08008157 processKey(mapper, BTN_LEFT, 0);
8158 processSync(mapper);
8159 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008160 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008161 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008162
8163 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008164 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008165 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008166
8167 // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
8168 processKey(mapper, BTN_RIGHT, 1);
8169 processKey(mapper, BTN_MIDDLE, 1);
8170 processSync(mapper);
8171 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8172 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
8173 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
8174 motionArgs.buttonState);
8175
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008176 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8177 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8178 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
8179
8180 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8181 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8182 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
8183 motionArgs.buttonState);
8184
Michael Wrightd02c5b62014-02-10 15:10:22 -08008185 processKey(mapper, BTN_RIGHT, 0);
8186 processSync(mapper);
8187 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008188 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008189 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008190
8191 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008192 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008193 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008194
8195 processKey(mapper, BTN_MIDDLE, 0);
8196 processSync(mapper);
8197 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008198 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008199 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008200
8201 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008202 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008203 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008204
8205 // press BTN_BACK, release BTN_BACK
8206 processKey(mapper, BTN_BACK, 1);
8207 processSync(mapper);
8208 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8209 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8210 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008211
Michael Wrightd02c5b62014-02-10 15:10:22 -08008212 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008213 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008214 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
8215
8216 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8217 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8218 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008219
8220 processKey(mapper, BTN_BACK, 0);
8221 processSync(mapper);
8222 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008223 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008224 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008225
8226 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008227 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008228 ASSERT_EQ(0, motionArgs.buttonState);
8229
Michael Wrightd02c5b62014-02-10 15:10:22 -08008230 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8231 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8232 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
8233
8234 // press BTN_SIDE, release BTN_SIDE
8235 processKey(mapper, BTN_SIDE, 1);
8236 processSync(mapper);
8237 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8238 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8239 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008240
Michael Wrightd02c5b62014-02-10 15:10:22 -08008241 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008242 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008243 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
8244
8245 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8246 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8247 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008248
8249 processKey(mapper, BTN_SIDE, 0);
8250 processSync(mapper);
8251 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008252 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008253 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008254
8255 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008256 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008257 ASSERT_EQ(0, motionArgs.buttonState);
8258
Michael Wrightd02c5b62014-02-10 15:10:22 -08008259 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8260 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8261 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
8262
8263 // press BTN_FORWARD, release BTN_FORWARD
8264 processKey(mapper, BTN_FORWARD, 1);
8265 processSync(mapper);
8266 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8267 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8268 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008269
Michael Wrightd02c5b62014-02-10 15:10:22 -08008270 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008271 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008272 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
8273
8274 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8275 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8276 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008277
8278 processKey(mapper, BTN_FORWARD, 0);
8279 processSync(mapper);
8280 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008281 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008282 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008283
8284 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008285 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008286 ASSERT_EQ(0, motionArgs.buttonState);
8287
Michael Wrightd02c5b62014-02-10 15:10:22 -08008288 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8289 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8290 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
8291
8292 // press BTN_EXTRA, release BTN_EXTRA
8293 processKey(mapper, BTN_EXTRA, 1);
8294 processSync(mapper);
8295 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8296 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8297 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008298
Michael Wrightd02c5b62014-02-10 15:10:22 -08008299 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008300 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008301 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
8302
8303 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8304 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8305 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008306
8307 processKey(mapper, BTN_EXTRA, 0);
8308 processSync(mapper);
8309 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008310 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008311 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008312
8313 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008314 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008315 ASSERT_EQ(0, motionArgs.buttonState);
8316
Michael Wrightd02c5b62014-02-10 15:10:22 -08008317 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8318 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8319 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
8320
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008321 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
8322
Michael Wrightd02c5b62014-02-10 15:10:22 -08008323 // press BTN_STYLUS, release BTN_STYLUS
8324 processKey(mapper, BTN_STYLUS, 1);
8325 processSync(mapper);
8326 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8327 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008328 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
8329
8330 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8331 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8332 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008333
8334 processKey(mapper, BTN_STYLUS, 0);
8335 processSync(mapper);
8336 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008337 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008338 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008339
8340 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008341 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008342 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008343
8344 // press BTN_STYLUS2, release BTN_STYLUS2
8345 processKey(mapper, BTN_STYLUS2, 1);
8346 processSync(mapper);
8347 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8348 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008349 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
8350
8351 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8352 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8353 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008354
8355 processKey(mapper, BTN_STYLUS2, 0);
8356 processSync(mapper);
8357 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008358 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008359 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008360
8361 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008362 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008363 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008364
8365 // release touch
8366 processId(mapper, -1);
8367 processSync(mapper);
8368 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8369 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8370 ASSERT_EQ(0, motionArgs.buttonState);
8371}
8372
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008373TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleMappedStylusButtons) {
8374 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008375 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008376 prepareAxes(POSITION | ID | SLOT);
Arpit Singha8c236b2023-04-25 13:56:05 +00008377 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008378
8379 mFakeEventHub->addKey(EVENTHUB_ID, BTN_A, 0, AKEYCODE_STYLUS_BUTTON_PRIMARY, 0);
8380 mFakeEventHub->addKey(EVENTHUB_ID, 0, 0xabcd, AKEYCODE_STYLUS_BUTTON_SECONDARY, 0);
8381
8382 // Touch down.
8383 processId(mapper, 1);
8384 processPosition(mapper, 100, 200);
8385 processSync(mapper);
8386 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8387 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithButtonState(0))));
8388
8389 // Press and release button mapped to the primary stylus button.
8390 processKey(mapper, BTN_A, 1);
8391 processSync(mapper);
8392 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8393 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
8394 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
8395 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8396 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
8397 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
8398
8399 processKey(mapper, BTN_A, 0);
8400 processSync(mapper);
8401 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8402 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithButtonState(0))));
8403 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8404 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
8405
8406 // Press and release the HID usage mapped to the secondary stylus button.
8407 processHidUsage(mapper, 0xabcd, 1);
8408 processSync(mapper);
8409 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8410 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
8411 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY))));
8412 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8413 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
8414 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY))));
8415
8416 processHidUsage(mapper, 0xabcd, 0);
8417 processSync(mapper);
8418 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8419 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithButtonState(0))));
8420 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8421 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
8422
8423 // Release touch.
8424 processId(mapper, -1);
8425 processSync(mapper);
8426 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8427 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
8428}
8429
Michael Wrightd02c5b62014-02-10 15:10:22 -08008430TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008431 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008432 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008433 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00008434 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008435
8436 NotifyMotionArgs motionArgs;
8437
8438 // default tool type is finger
8439 processId(mapper, 1);
8440 processPosition(mapper, 100, 200);
8441 processSync(mapper);
8442 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8443 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008444 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008445
8446 // eraser
8447 processKey(mapper, BTN_TOOL_RUBBER, 1);
8448 processSync(mapper);
8449 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8450 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008451 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008452
8453 // stylus
8454 processKey(mapper, BTN_TOOL_RUBBER, 0);
8455 processKey(mapper, BTN_TOOL_PEN, 1);
8456 processSync(mapper);
8457 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8458 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008459 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008460
8461 // brush
8462 processKey(mapper, BTN_TOOL_PEN, 0);
8463 processKey(mapper, BTN_TOOL_BRUSH, 1);
8464 processSync(mapper);
8465 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8466 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008467 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008468
8469 // pencil
8470 processKey(mapper, BTN_TOOL_BRUSH, 0);
8471 processKey(mapper, BTN_TOOL_PENCIL, 1);
8472 processSync(mapper);
8473 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8474 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008475 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008476
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08008477 // air-brush
Michael Wrightd02c5b62014-02-10 15:10:22 -08008478 processKey(mapper, BTN_TOOL_PENCIL, 0);
8479 processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
8480 processSync(mapper);
8481 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8482 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008483 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008484
8485 // mouse
8486 processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
8487 processKey(mapper, BTN_TOOL_MOUSE, 1);
8488 processSync(mapper);
8489 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8490 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008491 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008492
8493 // lens
8494 processKey(mapper, BTN_TOOL_MOUSE, 0);
8495 processKey(mapper, BTN_TOOL_LENS, 1);
8496 processSync(mapper);
8497 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8498 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008499 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008500
8501 // double-tap
8502 processKey(mapper, BTN_TOOL_LENS, 0);
8503 processKey(mapper, BTN_TOOL_DOUBLETAP, 1);
8504 processSync(mapper);
8505 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8506 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008507 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008508
8509 // triple-tap
8510 processKey(mapper, BTN_TOOL_DOUBLETAP, 0);
8511 processKey(mapper, BTN_TOOL_TRIPLETAP, 1);
8512 processSync(mapper);
8513 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8514 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008515 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008516
8517 // quad-tap
8518 processKey(mapper, BTN_TOOL_TRIPLETAP, 0);
8519 processKey(mapper, BTN_TOOL_QUADTAP, 1);
8520 processSync(mapper);
8521 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8522 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008523 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008524
8525 // finger
8526 processKey(mapper, BTN_TOOL_QUADTAP, 0);
8527 processKey(mapper, BTN_TOOL_FINGER, 1);
8528 processSync(mapper);
8529 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8530 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008531 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008532
8533 // stylus trumps finger
8534 processKey(mapper, BTN_TOOL_PEN, 1);
8535 processSync(mapper);
8536 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8537 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008538 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008539
8540 // eraser trumps stylus
8541 processKey(mapper, BTN_TOOL_RUBBER, 1);
8542 processSync(mapper);
8543 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8544 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008545 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008546
8547 // mouse trumps eraser
8548 processKey(mapper, BTN_TOOL_MOUSE, 1);
8549 processSync(mapper);
8550 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8551 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008552 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008553
8554 // MT tool type trumps BTN tool types: MT_TOOL_FINGER
8555 processToolType(mapper, MT_TOOL_FINGER); // this is the first time we send MT_TOOL_TYPE
8556 processSync(mapper);
8557 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8558 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008559 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008560
8561 // MT tool type trumps BTN tool types: MT_TOOL_PEN
8562 processToolType(mapper, MT_TOOL_PEN);
8563 processSync(mapper);
8564 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8565 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008566 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008567
8568 // back to default tool type
8569 processToolType(mapper, -1); // use a deliberately undefined tool type, for testing
8570 processKey(mapper, BTN_TOOL_MOUSE, 0);
8571 processKey(mapper, BTN_TOOL_RUBBER, 0);
8572 processKey(mapper, BTN_TOOL_PEN, 0);
8573 processKey(mapper, BTN_TOOL_FINGER, 0);
8574 processSync(mapper);
8575 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8576 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008577 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008578}
8579
8580TEST_F(MultiTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008581 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008582 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008583 prepareAxes(POSITION | ID | SLOT);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008584 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00008585 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008586
8587 NotifyMotionArgs motionArgs;
8588
8589 // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0
8590 processId(mapper, 1);
8591 processPosition(mapper, 100, 200);
8592 processSync(mapper);
8593 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8594 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8595 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8596 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8597
8598 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8599 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8600 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8601 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8602
8603 // move a little
8604 processPosition(mapper, 150, 250);
8605 processSync(mapper);
8606 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8607 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8608 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8609 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8610
8611 // down when BTN_TOUCH is pressed, pressure defaults to 1
8612 processKey(mapper, BTN_TOUCH, 1);
8613 processSync(mapper);
8614 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8615 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8616 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8617 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8618
8619 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8620 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8621 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8622 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8623
8624 // up when BTN_TOUCH is released, hover restored
8625 processKey(mapper, BTN_TOUCH, 0);
8626 processSync(mapper);
8627 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8628 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8629 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8630 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8631
8632 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8633 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8634 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8635 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8636
8637 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8638 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8639 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8640 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8641
8642 // exit hover when pointer goes away
8643 processId(mapper, -1);
8644 processSync(mapper);
8645 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8646 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8647 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8648 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8649}
8650
8651TEST_F(MultiTouchInputMapperTest, Process_WhenAbsMTPressureIsPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008652 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008653 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008654 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00008655 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008656
8657 NotifyMotionArgs motionArgs;
8658
8659 // initially hovering because pressure is 0
8660 processId(mapper, 1);
8661 processPosition(mapper, 100, 200);
8662 processPressure(mapper, 0);
8663 processSync(mapper);
8664 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8665 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8666 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8667 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8668
8669 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8670 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8671 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8672 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8673
8674 // move a little
8675 processPosition(mapper, 150, 250);
8676 processSync(mapper);
8677 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8678 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8679 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8680 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8681
8682 // down when pressure becomes non-zero
8683 processPressure(mapper, RAW_PRESSURE_MAX);
8684 processSync(mapper);
8685 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8686 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8687 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8688 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8689
8690 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8691 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8692 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8693 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8694
8695 // up when pressure becomes 0, hover restored
8696 processPressure(mapper, 0);
8697 processSync(mapper);
8698 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8699 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8700 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8701 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8702
8703 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8704 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8705 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8706 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8707
8708 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8709 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8710 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8711 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8712
8713 // exit hover when pointer goes away
8714 processId(mapper, -1);
8715 processSync(mapper);
8716 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8717 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8718 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8719 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8720}
8721
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008722/**
8723 * Set the input device port <--> display port associations, and check that the
8724 * events are routed to the display that matches the display port.
8725 * This can be checked by looking at the displayId of the resulting NotifyMotionArgs.
8726 */
8727TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayPort) {
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008728 const std::string usb2 = "USB2";
8729 const uint8_t hdmi1 = 0;
8730 const uint8_t hdmi2 = 1;
8731 const std::string secondaryUniqueId = "uniqueId2";
Michael Wrightfe3de7d2020-07-02 19:05:30 +01008732 constexpr ViewportType type = ViewportType::EXTERNAL;
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008733
8734 addConfigurationProperty("touch.deviceType", "touchScreen");
8735 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008736 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008737
8738 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
8739 mFakePolicy->addInputPortAssociation(usb2, hdmi2);
8740
8741 // We are intentionally not adding the viewport for display 1 yet. Since the port association
8742 // for this input device is specified, and the matching viewport is not present,
8743 // the input device should be disabled (at the mapper level).
8744
8745 // Add viewport for display 2 on hdmi2
8746 prepareSecondaryDisplay(type, hdmi2);
8747 // Send a touch event
8748 processPosition(mapper, 100, 100);
8749 processSync(mapper);
8750 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
8751
8752 // Add viewport for display 1 on hdmi1
Michael Wrighta9cf4192022-12-01 23:46:39 +00008753 prepareDisplay(ui::ROTATION_0, hdmi1);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008754 // Send a touch event again
8755 processPosition(mapper, 100, 100);
8756 processSync(mapper);
8757
8758 NotifyMotionArgs args;
8759 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8760 ASSERT_EQ(DISPLAY_ID, args.displayId);
8761}
Michael Wrightd02c5b62014-02-10 15:10:22 -08008762
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008763TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayUniqueId) {
8764 addConfigurationProperty("touch.deviceType", "touchScreen");
8765 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008766 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008767
8768 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID);
8769
Michael Wrighta9cf4192022-12-01 23:46:39 +00008770 prepareDisplay(ui::ROTATION_0);
8771 prepareVirtualDisplay(ui::ROTATION_0);
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008772
8773 // Send a touch event
8774 processPosition(mapper, 100, 100);
8775 processSync(mapper);
8776
8777 NotifyMotionArgs args;
8778 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8779 ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId);
8780}
8781
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008782TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01008783 prepareSecondaryDisplay(ViewportType::EXTERNAL);
Garfield Tan888a6a42020-01-09 11:39:16 -08008784
Michael Wrighta9cf4192022-12-01 23:46:39 +00008785 prepareDisplay(ui::ROTATION_0);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008786 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008787 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008788
Josep del Río2d8c79a2023-01-23 19:33:50 +00008789 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008790
8791 NotifyMotionArgs motionArgs;
8792 processPosition(mapper, 100, 100);
8793 processSync(mapper);
8794
8795 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8796 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008797 ASSERT_EQ(ui::LogicalDisplayId::INVALID, motionArgs.displayId);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008798}
8799
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008800/**
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008801 * Ensure that the readTime is set to the SYN_REPORT value when processing touch events.
8802 */
8803TEST_F(MultiTouchInputMapperTest, Process_SendsReadTime) {
8804 addConfigurationProperty("touch.deviceType", "touchScreen");
8805 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008806 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008807
Michael Wrighta9cf4192022-12-01 23:46:39 +00008808 prepareDisplay(ui::ROTATION_0);
Harry Cutts33476232023-01-30 19:57:29 +00008809 process(mapper, 10, /*readTime=*/11, EV_ABS, ABS_MT_TRACKING_ID, 1);
8810 process(mapper, 15, /*readTime=*/16, EV_ABS, ABS_MT_POSITION_X, 100);
8811 process(mapper, 20, /*readTime=*/21, EV_ABS, ABS_MT_POSITION_Y, 100);
8812 process(mapper, 25, /*readTime=*/26, EV_SYN, SYN_REPORT, 0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008813
8814 NotifyMotionArgs args;
8815 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8816 ASSERT_EQ(26, args.readTime);
8817
Harry Cutts33476232023-01-30 19:57:29 +00008818 process(mapper, 30, /*readTime=*/31, EV_ABS, ABS_MT_POSITION_X, 110);
8819 process(mapper, 30, /*readTime=*/32, EV_ABS, ABS_MT_POSITION_Y, 220);
8820 process(mapper, 30, /*readTime=*/33, EV_SYN, SYN_REPORT, 0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008821
8822 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8823 ASSERT_EQ(33, args.readTime);
8824}
8825
8826/**
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008827 * When the viewport is not active (isActive=false), the touch mapper should be disabled and the
8828 * events should not be delivered to the listener.
8829 */
8830TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreDropped) {
8831 addConfigurationProperty("touch.deviceType", "touchScreen");
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008832 // Don't set touch.enableForInactiveViewport to verify the default behavior.
Michael Wrighta9cf4192022-12-01 23:46:39 +00008833 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008834 /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008835 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008836 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008837 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008838
8839 NotifyMotionArgs motionArgs;
8840 processPosition(mapper, 100, 100);
8841 processSync(mapper);
8842
8843 mFakeListener->assertNotifyMotionWasNotCalled();
8844}
8845
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008846/**
8847 * When the viewport is not active (isActive=false) and touch.enableForInactiveViewport is true,
8848 * the touch mapper can process the events and the events can be delivered to the listener.
8849 */
8850TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreProcessed) {
8851 addConfigurationProperty("touch.deviceType", "touchScreen");
8852 addConfigurationProperty("touch.enableForInactiveViewport", "1");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008853 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008854 /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008855 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008856 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008857 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008858
8859 NotifyMotionArgs motionArgs;
8860 processPosition(mapper, 100, 100);
8861 processSync(mapper);
8862
8863 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8864 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8865}
8866
Josh Thielene986aed2023-06-01 14:17:30 +00008867/**
8868 * When the viewport is deactivated (isActive transitions from true to false),
8869 * and touch.enableForInactiveViewport is false, touches prior to the transition
8870 * should be cancelled.
8871 */
Garfield Tanc734e4f2021-01-15 20:01:39 -08008872TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_AbortTouches) {
8873 addConfigurationProperty("touch.deviceType", "touchScreen");
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008874 addConfigurationProperty("touch.enableForInactiveViewport", "0");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008875 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008876 /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008877 std::optional<DisplayViewport> optionalDisplayViewport =
8878 mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
8879 ASSERT_TRUE(optionalDisplayViewport.has_value());
8880 DisplayViewport displayViewport = *optionalDisplayViewport;
8881
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008882 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008883 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008884 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Garfield Tanc734e4f2021-01-15 20:01:39 -08008885
8886 // Finger down
8887 int32_t x = 100, y = 100;
8888 processPosition(mapper, x, y);
8889 processSync(mapper);
8890
8891 NotifyMotionArgs motionArgs;
8892 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8893 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8894
8895 // Deactivate display viewport
8896 displayViewport.isActive = false;
8897 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008898 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008899
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008900 // The ongoing touch should be canceled immediately
8901 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8902 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
8903
8904 // Finger move is ignored
Garfield Tanc734e4f2021-01-15 20:01:39 -08008905 x += 10, y += 10;
8906 processPosition(mapper, x, y);
8907 processSync(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008908 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
Garfield Tanc734e4f2021-01-15 20:01:39 -08008909
8910 // Reactivate display viewport
8911 displayViewport.isActive = true;
8912 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008913 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008914
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008915 // Finger move again starts new gesture
Garfield Tanc734e4f2021-01-15 20:01:39 -08008916 x += 10, y += 10;
8917 processPosition(mapper, x, y);
8918 processSync(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008919 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8920 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008921}
8922
Josh Thielene986aed2023-06-01 14:17:30 +00008923/**
8924 * When the viewport is deactivated (isActive transitions from true to false),
8925 * and touch.enableForInactiveViewport is true, touches prior to the transition
8926 * should not be cancelled.
8927 */
8928TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_TouchesNotAborted) {
8929 addConfigurationProperty("touch.deviceType", "touchScreen");
8930 addConfigurationProperty("touch.enableForInactiveViewport", "1");
8931 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
8932 /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
8933 std::optional<DisplayViewport> optionalDisplayViewport =
8934 mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
8935 ASSERT_TRUE(optionalDisplayViewport.has_value());
8936 DisplayViewport displayViewport = *optionalDisplayViewport;
8937
8938 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8939 prepareAxes(POSITION);
8940 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
8941
8942 // Finger down
8943 int32_t x = 100, y = 100;
8944 processPosition(mapper, x, y);
8945 processSync(mapper);
8946 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8947 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
8948
8949 // Deactivate display viewport
8950 displayViewport.isActive = false;
8951 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
8952 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8953
8954 // The ongoing touch should not be canceled
8955 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
8956
8957 // Finger move is not ignored
8958 x += 10, y += 10;
8959 processPosition(mapper, x, y);
8960 processSync(mapper);
8961 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8962 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
8963
8964 // Reactivate display viewport
8965 displayViewport.isActive = true;
8966 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
8967 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8968
8969 // Finger move continues and does not start new gesture
8970 x += 10, y += 10;
8971 processPosition(mapper, x, y);
8972 processSync(mapper);
8973 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8974 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
8975}
8976
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008977TEST_F(MultiTouchInputMapperTest, VideoFrames_ReceivedByListener) {
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008978 prepareAxes(POSITION);
8979 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008980 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00008981 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008982
8983 NotifyMotionArgs motionArgs;
8984 // Unrotated video frame
8985 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8986 std::vector<TouchVideoFrame> frames{frame};
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008987 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008988 processPosition(mapper, 100, 200);
8989 processSync(mapper);
8990 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8991 ASSERT_EQ(frames, motionArgs.videoFrames);
8992
8993 // Subsequent touch events should not have any videoframes
8994 // This is implemented separately in FakeEventHub,
8995 // but that should match the behaviour of TouchVideoDevice.
8996 processPosition(mapper, 200, 200);
8997 processSync(mapper);
8998 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8999 ASSERT_EQ(std::vector<TouchVideoFrame>(), motionArgs.videoFrames);
9000}
9001
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009002TEST_F(MultiTouchInputMapperTest, VideoFrames_AreNotRotated) {
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009003 prepareAxes(POSITION);
9004 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00009005 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009006 // Unrotated video frame
9007 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
9008 NotifyMotionArgs motionArgs;
9009
9010 // Test all 4 orientations
Michael Wrighta9cf4192022-12-01 23:46:39 +00009011 for (ui::Rotation orientation : ftl::enum_range<ui::Rotation>()) {
Harry Cuttsc57cd3c2024-04-24 13:52:55 +00009012 SCOPED_TRACE(StringPrintf("Orientation %s", ftl::enum_string(orientation).c_str()));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009013 clearViewports();
9014 prepareDisplay(orientation);
9015 std::vector<TouchVideoFrame> frames{frame};
9016 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
9017 processPosition(mapper, 100, 200);
9018 processSync(mapper);
9019 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9020 ASSERT_EQ(frames, motionArgs.videoFrames);
9021 }
9022}
9023
9024TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_AreRotated) {
9025 prepareAxes(POSITION);
9026 addConfigurationProperty("touch.deviceType", "touchScreen");
9027 // Since InputReader works in the un-rotated coordinate space, only devices that are not
9028 // orientation-aware are affected by display rotation.
9029 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00009030 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009031 // Unrotated video frame
9032 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
9033 NotifyMotionArgs motionArgs;
9034
9035 // Test all 4 orientations
Michael Wrighta9cf4192022-12-01 23:46:39 +00009036 for (ui::Rotation orientation : ftl::enum_range<ui::Rotation>()) {
Harry Cuttsc57cd3c2024-04-24 13:52:55 +00009037 SCOPED_TRACE(StringPrintf("Orientation %s", ftl::enum_string(orientation).c_str()));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009038 clearViewports();
9039 prepareDisplay(orientation);
9040 std::vector<TouchVideoFrame> frames{frame};
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009041 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009042 processPosition(mapper, 100, 200);
9043 processSync(mapper);
9044 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009045 // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction
9046 // compared to the display. This is so that when the window transform (which contains the
9047 // display rotation) is applied later by InputDispatcher, the coordinates end up in the
9048 // window's coordinate space.
9049 frames[0].rotate(getInverseRotation(orientation));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009050 ASSERT_EQ(frames, motionArgs.videoFrames);
lilinnan687e58f2022-07-19 16:00:50 +08009051
9052 // Release finger.
9053 processSync(mapper);
9054 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009055 }
9056}
9057
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009058TEST_F(MultiTouchInputMapperTest, VideoFrames_MultipleFramesAreNotRotated) {
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009059 prepareAxes(POSITION);
9060 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00009061 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009062 // Unrotated video frames. There's no rule that they must all have the same dimensions,
9063 // so mix these.
9064 TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
9065 TouchVideoFrame frame2(3, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {1, 3});
9066 TouchVideoFrame frame3(2, 2, {10, 20, 10, 0}, {1, 4});
9067 std::vector<TouchVideoFrame> frames{frame1, frame2, frame3};
9068 NotifyMotionArgs motionArgs;
9069
Michael Wrighta9cf4192022-12-01 23:46:39 +00009070 prepareDisplay(ui::ROTATION_90);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009071 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009072 processPosition(mapper, 100, 200);
9073 processSync(mapper);
9074 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009075 ASSERT_EQ(frames, motionArgs.videoFrames);
9076}
9077
9078TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_MultipleFramesAreRotated) {
9079 prepareAxes(POSITION);
9080 addConfigurationProperty("touch.deviceType", "touchScreen");
9081 // Since InputReader works in the un-rotated coordinate space, only devices that are not
9082 // orientation-aware are affected by display rotation.
9083 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00009084 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009085 // Unrotated video frames. There's no rule that they must all have the same dimensions,
9086 // so mix these.
9087 TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
9088 TouchVideoFrame frame2(3, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {1, 3});
9089 TouchVideoFrame frame3(2, 2, {10, 20, 10, 0}, {1, 4});
9090 std::vector<TouchVideoFrame> frames{frame1, frame2, frame3};
9091 NotifyMotionArgs motionArgs;
9092
Michael Wrighta9cf4192022-12-01 23:46:39 +00009093 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009094 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
9095 processPosition(mapper, 100, 200);
9096 processSync(mapper);
9097 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9098 std::for_each(frames.begin(), frames.end(), [](TouchVideoFrame& frame) {
9099 // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction
9100 // compared to the display. This is so that when the window transform (which contains the
9101 // display rotation) is applied later by InputDispatcher, the coordinates end up in the
9102 // window's coordinate space.
Michael Wrighta9cf4192022-12-01 23:46:39 +00009103 frame.rotate(getInverseRotation(ui::ROTATION_90));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009104 });
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009105 ASSERT_EQ(frames, motionArgs.videoFrames);
9106}
9107
Arthur Hung9da14732019-09-02 16:16:58 +08009108/**
9109 * If we had defined port associations, but the viewport is not ready, the touch device would be
9110 * expected to be disabled, and it should be enabled after the viewport has found.
9111 */
9112TEST_F(MultiTouchInputMapperTest, Configure_EnabledForAssociatedDisplay) {
Arthur Hung9da14732019-09-02 16:16:58 +08009113 constexpr uint8_t hdmi2 = 1;
9114 const std::string secondaryUniqueId = "uniqueId2";
Michael Wrightfe3de7d2020-07-02 19:05:30 +01009115 constexpr ViewportType type = ViewportType::EXTERNAL;
Arthur Hung9da14732019-09-02 16:16:58 +08009116
9117 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi2);
9118
9119 addConfigurationProperty("touch.deviceType", "touchScreen");
9120 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00009121 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung9da14732019-09-02 16:16:58 +08009122
9123 ASSERT_EQ(mDevice->isEnabled(), false);
9124
9125 // Add display on hdmi2, the device should be enabled and can receive touch event.
9126 prepareSecondaryDisplay(type, hdmi2);
9127 ASSERT_EQ(mDevice->isEnabled(), true);
9128
9129 // Send a touch event.
9130 processPosition(mapper, 100, 100);
9131 processSync(mapper);
9132
9133 NotifyMotionArgs args;
9134 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9135 ASSERT_EQ(SECONDARY_DISPLAY_ID, args.displayId);
9136}
9137
Arthur Hung421eb1c2020-01-16 00:09:42 +08009138TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleSingleTouch) {
Arthur Hung421eb1c2020-01-16 00:09:42 +08009139 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009140 prepareDisplay(ui::ROTATION_0);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009141 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009142 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung421eb1c2020-01-16 00:09:42 +08009143
9144 NotifyMotionArgs motionArgs;
9145
9146 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
9147 // finger down
9148 processId(mapper, 1);
9149 processPosition(mapper, x1, y1);
9150 processSync(mapper);
9151 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9152 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009153 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009154
9155 // finger move
9156 processId(mapper, 1);
9157 processPosition(mapper, x2, y2);
9158 processSync(mapper);
9159 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9160 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009161 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009162
9163 // finger up.
9164 processId(mapper, -1);
9165 processSync(mapper);
9166 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9167 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009168 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009169
9170 // new finger down
9171 processId(mapper, 1);
9172 processPosition(mapper, x3, y3);
9173 processSync(mapper);
9174 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9175 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009176 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009177}
9178
9179/**
arthurhungcc7f9802020-04-30 17:55:40 +08009180 * Test single touch should be canceled when received the MT_TOOL_PALM event, and the following
9181 * MOVE and UP events should be ignored.
Arthur Hung421eb1c2020-01-16 00:09:42 +08009182 */
arthurhungcc7f9802020-04-30 17:55:40 +08009183TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_SinglePointer) {
Arthur Hung421eb1c2020-01-16 00:09:42 +08009184 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009185 prepareDisplay(ui::ROTATION_0);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009186 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009187 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung421eb1c2020-01-16 00:09:42 +08009188
9189 NotifyMotionArgs motionArgs;
9190
9191 // default tool type is finger
9192 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
arthurhungcc7f9802020-04-30 17:55:40 +08009193 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009194 processPosition(mapper, x1, y1);
9195 processSync(mapper);
9196 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9197 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009198 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009199
9200 // Tool changed to MT_TOOL_PALM expect sending the cancel event.
9201 processToolType(mapper, MT_TOOL_PALM);
9202 processSync(mapper);
9203 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9204 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9205
9206 // Ignore the following MOVE and UP events if had detect a palm event.
arthurhungcc7f9802020-04-30 17:55:40 +08009207 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009208 processPosition(mapper, x2, y2);
9209 processSync(mapper);
9210 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9211
9212 // finger up.
arthurhungcc7f9802020-04-30 17:55:40 +08009213 processId(mapper, INVALID_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009214 processSync(mapper);
9215 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9216
9217 // new finger down
arthurhungcc7f9802020-04-30 17:55:40 +08009218 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009219 processToolType(mapper, MT_TOOL_FINGER);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009220 processPosition(mapper, x3, y3);
9221 processSync(mapper);
9222 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9223 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009224 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009225}
9226
arthurhungbf89a482020-04-17 17:37:55 +08009227/**
arthurhungcc7f9802020-04-30 17:55:40 +08009228 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event from some finger,
9229 * and the rest active fingers could still be allowed to receive the events
arthurhungbf89a482020-04-17 17:37:55 +08009230 */
arthurhungcc7f9802020-04-30 17:55:40 +08009231TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_TwoPointers) {
arthurhungbf89a482020-04-17 17:37:55 +08009232 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009233 prepareDisplay(ui::ROTATION_0);
arthurhungbf89a482020-04-17 17:37:55 +08009234 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009235 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungbf89a482020-04-17 17:37:55 +08009236
9237 NotifyMotionArgs motionArgs;
9238
9239 // default tool type is finger
arthurhungcc7f9802020-04-30 17:55:40 +08009240 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220;
9241 processId(mapper, FIRST_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009242 processPosition(mapper, x1, y1);
9243 processSync(mapper);
9244 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9245 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009246 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungbf89a482020-04-17 17:37:55 +08009247
9248 // Second finger down.
arthurhungcc7f9802020-04-30 17:55:40 +08009249 processSlot(mapper, SECOND_SLOT);
9250 processId(mapper, SECOND_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009251 processPosition(mapper, x2, y2);
arthurhungcc7f9802020-04-30 17:55:40 +08009252 processSync(mapper);
9253 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009254 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009255 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009256
9257 // If the tool type of the first finger changes to MT_TOOL_PALM,
9258 // we expect to receive ACTION_POINTER_UP with cancel flag.
9259 processSlot(mapper, FIRST_SLOT);
9260 processId(mapper, FIRST_TRACKING_ID);
9261 processToolType(mapper, MT_TOOL_PALM);
9262 processSync(mapper);
9263 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009264 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009265 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9266
9267 // The following MOVE events of second finger should be processed.
9268 processSlot(mapper, SECOND_SLOT);
9269 processId(mapper, SECOND_TRACKING_ID);
9270 processPosition(mapper, x2 + 1, y2 + 1);
9271 processSync(mapper);
9272 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9273 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009274 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009275
9276 // First finger up. It used to be in palm mode, and we already generated ACTION_POINTER_UP for
9277 // it. Second finger receive move.
9278 processSlot(mapper, FIRST_SLOT);
9279 processId(mapper, INVALID_TRACKING_ID);
9280 processSync(mapper);
9281 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9282 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009283 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009284
9285 // Second finger keeps moving.
9286 processSlot(mapper, SECOND_SLOT);
9287 processId(mapper, SECOND_TRACKING_ID);
9288 processPosition(mapper, x2 + 2, y2 + 2);
9289 processSync(mapper);
9290 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9291 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009292 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009293
9294 // Second finger up.
9295 processId(mapper, INVALID_TRACKING_ID);
9296 processSync(mapper);
9297 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9298 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9299 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9300}
9301
9302/**
9303 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event, if only 1 finger
9304 * is active, it should send CANCEL after receiving the MT_TOOL_PALM event.
9305 */
9306TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_ShouldCancelWhenAllTouchIsPalm) {
9307 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009308 prepareDisplay(ui::ROTATION_0);
arthurhungcc7f9802020-04-30 17:55:40 +08009309 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009310 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungcc7f9802020-04-30 17:55:40 +08009311
9312 NotifyMotionArgs motionArgs;
9313
9314 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
9315 // First finger down.
9316 processId(mapper, FIRST_TRACKING_ID);
9317 processPosition(mapper, x1, y1);
9318 processSync(mapper);
9319 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9320 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009321 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009322
9323 // Second finger down.
9324 processSlot(mapper, SECOND_SLOT);
9325 processId(mapper, SECOND_TRACKING_ID);
9326 processPosition(mapper, x2, y2);
arthurhungbf89a482020-04-17 17:37:55 +08009327 processSync(mapper);
9328 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009329 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009330 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungbf89a482020-04-17 17:37:55 +08009331
arthurhungcc7f9802020-04-30 17:55:40 +08009332 // If the tool type of the first finger changes to MT_TOOL_PALM,
9333 // we expect to receive ACTION_POINTER_UP with cancel flag.
9334 processSlot(mapper, FIRST_SLOT);
9335 processId(mapper, FIRST_TRACKING_ID);
9336 processToolType(mapper, MT_TOOL_PALM);
9337 processSync(mapper);
9338 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009339 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009340 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9341
9342 // Second finger keeps moving.
9343 processSlot(mapper, SECOND_SLOT);
9344 processId(mapper, SECOND_TRACKING_ID);
9345 processPosition(mapper, x2 + 1, y2 + 1);
9346 processSync(mapper);
9347 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9348 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9349
9350 // second finger becomes palm, receive cancel due to only 1 finger is active.
9351 processId(mapper, SECOND_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009352 processToolType(mapper, MT_TOOL_PALM);
9353 processSync(mapper);
9354 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9355 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9356
arthurhungcc7f9802020-04-30 17:55:40 +08009357 // third finger down.
9358 processSlot(mapper, THIRD_SLOT);
9359 processId(mapper, THIRD_TRACKING_ID);
9360 processToolType(mapper, MT_TOOL_FINGER);
arthurhungbf89a482020-04-17 17:37:55 +08009361 processPosition(mapper, x3, y3);
9362 processSync(mapper);
arthurhungbf89a482020-04-17 17:37:55 +08009363 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9364 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009365 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009366 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009367
9368 // third finger move
9369 processId(mapper, THIRD_TRACKING_ID);
9370 processPosition(mapper, x3 + 1, y3 + 1);
9371 processSync(mapper);
9372 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9373 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9374
9375 // first finger up, third finger receive move.
9376 processSlot(mapper, FIRST_SLOT);
9377 processId(mapper, INVALID_TRACKING_ID);
9378 processSync(mapper);
9379 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9380 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009381 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009382
9383 // second finger up, third finger receive move.
9384 processSlot(mapper, SECOND_SLOT);
9385 processId(mapper, INVALID_TRACKING_ID);
9386 processSync(mapper);
9387 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9388 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009389 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009390
9391 // third finger up.
9392 processSlot(mapper, THIRD_SLOT);
9393 processId(mapper, INVALID_TRACKING_ID);
9394 processSync(mapper);
9395 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9396 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9397 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9398}
9399
9400/**
9401 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event from some finger,
9402 * and the active finger could still be allowed to receive the events
9403 */
9404TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_KeepFirstPointer) {
9405 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009406 prepareDisplay(ui::ROTATION_0);
arthurhungcc7f9802020-04-30 17:55:40 +08009407 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009408 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungcc7f9802020-04-30 17:55:40 +08009409
9410 NotifyMotionArgs motionArgs;
9411
9412 // default tool type is finger
9413 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220;
9414 processId(mapper, FIRST_TRACKING_ID);
9415 processPosition(mapper, x1, y1);
9416 processSync(mapper);
9417 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9418 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009419 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009420
9421 // Second finger down.
9422 processSlot(mapper, SECOND_SLOT);
9423 processId(mapper, SECOND_TRACKING_ID);
9424 processPosition(mapper, x2, y2);
9425 processSync(mapper);
9426 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009427 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009428 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009429
9430 // If the tool type of the second finger changes to MT_TOOL_PALM,
9431 // we expect to receive ACTION_POINTER_UP with cancel flag.
9432 processId(mapper, SECOND_TRACKING_ID);
9433 processToolType(mapper, MT_TOOL_PALM);
9434 processSync(mapper);
9435 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009436 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009437 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9438
9439 // The following MOVE event should be processed.
9440 processSlot(mapper, FIRST_SLOT);
9441 processId(mapper, FIRST_TRACKING_ID);
9442 processPosition(mapper, x1 + 1, y1 + 1);
9443 processSync(mapper);
9444 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9445 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009446 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009447
9448 // second finger up.
9449 processSlot(mapper, SECOND_SLOT);
9450 processId(mapper, INVALID_TRACKING_ID);
9451 processSync(mapper);
9452 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9453 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9454
9455 // first finger keep moving
9456 processSlot(mapper, FIRST_SLOT);
9457 processId(mapper, FIRST_TRACKING_ID);
9458 processPosition(mapper, x1 + 2, y1 + 2);
9459 processSync(mapper);
9460 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9461 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9462
9463 // first finger up.
9464 processId(mapper, INVALID_TRACKING_ID);
9465 processSync(mapper);
9466 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9467 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9468 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
arthurhungbf89a482020-04-17 17:37:55 +08009469}
9470
Arthur Hung9ad18942021-06-19 02:04:46 +00009471/**
9472 * Test multi-touch should sent ACTION_POINTER_UP/ACTION_UP when received the INVALID_TRACKING_ID,
9473 * to prevent the driver side may send unexpected data after set tracking id as INVALID_TRACKING_ID
9474 * cause slot be valid again.
9475 */
9476TEST_F(MultiTouchInputMapperTest, Process_MultiTouch_WithInvalidTrackingId) {
9477 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009478 prepareDisplay(ui::ROTATION_0);
Arthur Hung9ad18942021-06-19 02:04:46 +00009479 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009480 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung9ad18942021-06-19 02:04:46 +00009481
9482 NotifyMotionArgs motionArgs;
9483
9484 constexpr int32_t x1 = 100, y1 = 200, x2 = 0, y2 = 0;
9485 // First finger down.
9486 processId(mapper, FIRST_TRACKING_ID);
9487 processPosition(mapper, x1, y1);
9488 processPressure(mapper, RAW_PRESSURE_MAX);
9489 processSync(mapper);
9490 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9491 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009492 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009493
9494 // First finger move.
9495 processId(mapper, FIRST_TRACKING_ID);
9496 processPosition(mapper, x1 + 1, y1 + 1);
9497 processPressure(mapper, RAW_PRESSURE_MAX);
9498 processSync(mapper);
9499 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9500 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009501 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009502
9503 // Second finger down.
9504 processSlot(mapper, SECOND_SLOT);
9505 processId(mapper, SECOND_TRACKING_ID);
9506 processPosition(mapper, x2, y2);
9507 processPressure(mapper, RAW_PRESSURE_MAX);
9508 processSync(mapper);
9509 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009510 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009511 ASSERT_EQ(uint32_t(2), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009512
9513 // second finger up with some unexpected data.
9514 processSlot(mapper, SECOND_SLOT);
9515 processId(mapper, INVALID_TRACKING_ID);
9516 processPosition(mapper, x2, y2);
9517 processSync(mapper);
9518 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009519 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009520 ASSERT_EQ(uint32_t(2), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009521
9522 // first finger up with some unexpected data.
9523 processSlot(mapper, FIRST_SLOT);
9524 processId(mapper, INVALID_TRACKING_ID);
9525 processPosition(mapper, x2, y2);
9526 processPressure(mapper, RAW_PRESSURE_MAX);
9527 processSync(mapper);
9528 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9529 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009530 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009531}
9532
Arpit Singh4b4a4572023-11-24 18:19:56 +00009533TEST_F(MultiTouchInputMapperTest, Reset_RepopulatesMultiTouchState) {
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009534 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009535 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009536 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009537 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009538
9539 // First finger down.
Arpit Singh4b4a4572023-11-24 18:19:56 +00009540 constexpr int32_t x1 = 100, y1 = 200, x2 = 300, y2 = 400;
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009541 processId(mapper, FIRST_TRACKING_ID);
Arpit Singh4b4a4572023-11-24 18:19:56 +00009542 processPosition(mapper, x1, y1);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009543 processPressure(mapper, RAW_PRESSURE_MAX);
9544 processSync(mapper);
9545 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9546 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
9547
9548 // Second finger down.
9549 processSlot(mapper, SECOND_SLOT);
9550 processId(mapper, SECOND_TRACKING_ID);
Arpit Singh4b4a4572023-11-24 18:19:56 +00009551 processPosition(mapper, x2, y2);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009552 processPressure(mapper, RAW_PRESSURE_MAX);
9553 processSync(mapper);
9554 ASSERT_NO_FATAL_FAILURE(
9555 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(ACTION_POINTER_1_DOWN)));
9556
Arpit Singh4b4a4572023-11-24 18:19:56 +00009557 // Set MT Slot state to be repopulated for the required slots
9558 std::vector<int32_t> mtSlotValues(RAW_SLOT_MAX + 1, -1);
9559 mtSlotValues[0] = FIRST_TRACKING_ID;
9560 mtSlotValues[1] = SECOND_TRACKING_ID;
9561 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_TRACKING_ID, mtSlotValues);
9562
9563 mtSlotValues[0] = x1;
9564 mtSlotValues[1] = x2;
9565 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_POSITION_X, mtSlotValues);
9566
9567 mtSlotValues[0] = y1;
9568 mtSlotValues[1] = y2;
9569 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_POSITION_Y, mtSlotValues);
9570
9571 mtSlotValues[0] = RAW_PRESSURE_MAX;
9572 mtSlotValues[1] = RAW_PRESSURE_MAX;
9573 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_PRESSURE, mtSlotValues);
9574
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009575 // Reset the mapper. When the mapper is reset, we expect the current multi-touch state to be
Arpit Singh4b4a4572023-11-24 18:19:56 +00009576 // repopulated. Resetting should cancel the ongoing gesture.
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00009577 resetMapper(mapper, ARBITRARY_TIME);
9578 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9579 WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009580
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009581 // Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
9582 // the existing touch state to generate a down event.
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009583 processPosition(mapper, 301, 302);
9584 processSync(mapper);
9585 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9586 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPressure(1.f))));
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009587 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9588 AllOf(WithMotionAction(ACTION_POINTER_1_DOWN), WithPressure(1.f))));
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009589
9590 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9591}
9592
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009593TEST_F(MultiTouchInputMapperTest, Reset_PreservesLastTouchState_NoPointersDown) {
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009594 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009595 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009596 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009597 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009598
9599 // First finger touches down and releases.
9600 processId(mapper, FIRST_TRACKING_ID);
9601 processPosition(mapper, 100, 200);
9602 processPressure(mapper, RAW_PRESSURE_MAX);
9603 processSync(mapper);
9604 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9605 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
9606 processId(mapper, INVALID_TRACKING_ID);
9607 processSync(mapper);
9608 ASSERT_NO_FATAL_FAILURE(
9609 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
9610
9611 // Reset the mapper. When the mapper is reset, we expect it to restore the latest
9612 // raw state where no pointers are down.
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00009613 resetMapper(mapper, ARBITRARY_TIME);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009614 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9615
9616 // Send an empty sync frame. Since there are no pointers, no events are generated.
9617 processSync(mapper);
9618 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9619}
9620
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009621TEST_F(MultiTouchInputMapperTest, StylusSourceIsAddedDynamicallyFromToolType) {
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009622 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009623 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009624 prepareAxes(POSITION | ID | SLOT | PRESSURE | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009625 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009626 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009627
9628 // Even if the device supports reporting the ABS_MT_TOOL_TYPE axis, which could give it the
9629 // ability to report MT_TOOL_PEN, we do not report the device as coming from a stylus source.
9630 // Due to limitations in the evdev protocol, we cannot say for certain that a device is capable
9631 // of reporting stylus events just because it supports ABS_MT_TOOL_TYPE.
9632 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
9633
9634 // However, if the device ever ends up reporting an event with MT_TOOL_PEN, it should be
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009635 // reported with the stylus source.
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009636 processId(mapper, FIRST_TRACKING_ID);
9637 processToolType(mapper, MT_TOOL_PEN);
9638 processPosition(mapper, 100, 200);
9639 processPressure(mapper, RAW_PRESSURE_MAX);
9640 processSync(mapper);
9641 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9642 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
9643 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009644 WithToolType(ToolType::STYLUS))));
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009645
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009646 // Now that we know the device supports styluses, ensure that the device is re-configured with
9647 // the stylus source.
9648 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, mapper.getSources());
9649 {
9650 const auto& devices = mReader->getInputDevices();
9651 auto deviceInfo =
9652 std::find_if(devices.begin(), devices.end(),
9653 [](const InputDeviceInfo& info) { return info.getId() == DEVICE_ID; });
9654 LOG_ALWAYS_FATAL_IF(deviceInfo == devices.end(), "Cannot find InputDevice");
9655 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, deviceInfo->getSources());
9656 }
9657
9658 // Ensure the device was not reset to prevent interruptions of any ongoing gestures.
9659 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
9660
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009661 processId(mapper, INVALID_TRACKING_ID);
9662 processSync(mapper);
9663 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9664 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
9665 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009666 WithToolType(ToolType::STYLUS))));
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009667}
9668
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009669// --- MultiTouchInputMapperTest_ExternalDevice ---
9670
9671class MultiTouchInputMapperTest_ExternalDevice : public MultiTouchInputMapperTest {
9672protected:
Chris Yea52ade12020-08-27 16:49:20 -07009673 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL); }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009674};
9675
9676/**
9677 * Expect fallback to internal viewport if device is external and external viewport is not present.
9678 */
9679TEST_F(MultiTouchInputMapperTest_ExternalDevice, Viewports_Fallback) {
9680 prepareAxes(POSITION);
9681 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009682 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00009683 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009684
9685 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
9686
9687 NotifyMotionArgs motionArgs;
9688
9689 // Expect the event to be sent to the internal viewport,
9690 // because an external viewport is not present.
9691 processPosition(mapper, 100, 100);
9692 processSync(mapper);
9693 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009694 ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, motionArgs.displayId);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009695
9696 // Expect the event to be sent to the external viewport if it is present.
Michael Wrightfe3de7d2020-07-02 19:05:30 +01009697 prepareSecondaryDisplay(ViewportType::EXTERNAL);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009698 processPosition(mapper, 100, 100);
9699 processSync(mapper);
9700 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9701 ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
9702}
Arthur Hung4197f6b2020-03-16 15:39:59 +08009703
Prabir Pradhan3ed7e352024-05-03 23:59:43 +00009704// TODO(b/281840344): Remove the test when the old touchpad stack is removed. It is currently
9705// unclear what the behavior of the touchpad logic in TouchInputMapper should do after the
9706// PointerChoreographer refactor.
9707TEST_F(MultiTouchInputMapperTest, DISABLED_Process_TouchpadPointer) {
Harry Cutts8722be92024-04-05 14:46:05 +00009708 // prepare device
Michael Wrighta9cf4192022-12-01 23:46:39 +00009709 prepareDisplay(ui::ROTATION_0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009710 prepareAxes(POSITION | ID | SLOT);
9711 mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
9712 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00009713 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009714 // run uncaptured pointer tests - pushes out generic events
9715 // FINGER 0 DOWN
9716 processId(mapper, 3);
9717 processPosition(mapper, 100, 100);
9718 processKey(mapper, BTN_TOUCH, 1);
9719 processSync(mapper);
9720
9721 // start at (100,100), cursor should be at (0,0) * scale
9722 NotifyMotionArgs args;
9723 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9724 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
9725 ASSERT_NO_FATAL_FAILURE(
9726 assertPointerCoords(args.pointerCoords[0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
9727
9728 // FINGER 0 MOVE
9729 processPosition(mapper, 200, 200);
9730 processSync(mapper);
9731
9732 // compute scaling to help with touch position checking
9733 float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
9734 float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
9735 float scale =
9736 mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
9737
9738 // translate from (100,100) -> (200,200), cursor should have changed to (100,100) * scale)
9739 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9740 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
9741 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], 100 * scale, 100 * scale, 0,
9742 0, 0, 0, 0, 0, 0, 0));
LiZhihong758eb562022-11-03 15:28:29 +08009743
9744 // BUTTON DOWN
9745 processKey(mapper, BTN_LEFT, 1);
9746 processSync(mapper);
9747
9748 // touchinputmapper design sends a move before button press
9749 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9750 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
9751 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9752 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, args.action);
9753
9754 // BUTTON UP
9755 processKey(mapper, BTN_LEFT, 0);
9756 processSync(mapper);
9757
9758 // touchinputmapper design sends a move after button release
9759 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9760 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, args.action);
9761 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9762 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009763}
9764
Harry Cutts8722be92024-04-05 14:46:05 +00009765TEST_F(MultiTouchInputMapperTest, Touchpad_GetSources) {
Michael Wrighta9cf4192022-12-01 23:46:39 +00009766 prepareDisplay(ui::ROTATION_0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009767 prepareAxes(POSITION | ID | SLOT);
9768 mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
Hiroki Sato25040232024-02-22 17:21:22 +09009769 mFakePolicy->setPointerCapture(/*window=*/nullptr);
Arpit Singha8c236b2023-04-25 13:56:05 +00009770 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009771
Josep del Río2d8c79a2023-01-23 19:33:50 +00009772 // uncaptured touchpad should be a pointer device
9773 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009774}
9775
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009776// --- BluetoothMultiTouchInputMapperTest ---
9777
9778class BluetoothMultiTouchInputMapperTest : public MultiTouchInputMapperTest {
9779protected:
9780 void SetUp() override {
9781 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL, BUS_BLUETOOTH);
9782 }
9783};
9784
9785TEST_F(BluetoothMultiTouchInputMapperTest, TimestampSmoothening) {
9786 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009787 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009788 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009789 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009790
9791 nsecs_t kernelEventTime = ARBITRARY_TIME;
9792 nsecs_t expectedEventTime = ARBITRARY_TIME;
9793 // Touch down.
9794 processId(mapper, FIRST_TRACKING_ID);
9795 processPosition(mapper, 100, 200);
9796 processPressure(mapper, RAW_PRESSURE_MAX);
9797 processSync(mapper, ARBITRARY_TIME);
9798 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9799 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithEventTime(ARBITRARY_TIME))));
9800
9801 // Process several events that come in quick succession, according to their timestamps.
9802 for (int i = 0; i < 3; i++) {
9803 constexpr static nsecs_t delta = ms2ns(1);
9804 static_assert(delta < MIN_BLUETOOTH_TIMESTAMP_DELTA);
9805 kernelEventTime += delta;
9806 expectedEventTime += MIN_BLUETOOTH_TIMESTAMP_DELTA;
9807
9808 processPosition(mapper, 101 + i, 201 + i);
9809 processSync(mapper, kernelEventTime);
9810 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9811 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
9812 WithEventTime(expectedEventTime))));
9813 }
9814
9815 // Release the touch.
9816 processId(mapper, INVALID_TRACKING_ID);
9817 processPressure(mapper, RAW_PRESSURE_MIN);
9818 processSync(mapper, ARBITRARY_TIME + ms2ns(50));
9819 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9820 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
9821 WithEventTime(ARBITRARY_TIME + ms2ns(50)))));
9822}
9823
9824// --- MultiTouchPointerModeTest ---
9825
HQ Liue6983c72022-04-19 22:14:56 +00009826class MultiTouchPointerModeTest : public MultiTouchInputMapperTest {
9827protected:
9828 float mPointerMovementScale;
9829 float mPointerXZoomScale;
9830 void preparePointerMode(int xAxisResolution, int yAxisResolution) {
9831 addConfigurationProperty("touch.deviceType", "pointer");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009832 prepareDisplay(ui::ROTATION_0);
HQ Liue6983c72022-04-19 22:14:56 +00009833
9834 prepareAxes(POSITION);
9835 prepareAbsoluteAxisResolution(xAxisResolution, yAxisResolution);
9836 // In order to enable swipe and freeform gesture in pointer mode, pointer capture
9837 // needs to be disabled, and the pointer gesture needs to be enabled.
Hiroki Sato25040232024-02-22 17:21:22 +09009838 mFakePolicy->setPointerCapture(/*window=*/nullptr);
HQ Liue6983c72022-04-19 22:14:56 +00009839 mFakePolicy->setPointerGestureEnabled(true);
HQ Liue6983c72022-04-19 22:14:56 +00009840
9841 float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
9842 float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
9843 mPointerMovementScale =
9844 mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
9845 mPointerXZoomScale =
9846 mFakePolicy->getPointerGestureZoomSpeedRatio() * displayDiagonal / rawDiagonal;
9847 }
9848
9849 void prepareAbsoluteAxisResolution(int xAxisResolution, int yAxisResolution) {
9850 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX,
9851 /*flat*/ 0,
9852 /*fuzz*/ 0, /*resolution*/ xAxisResolution);
9853 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX,
9854 /*flat*/ 0,
9855 /*fuzz*/ 0, /*resolution*/ yAxisResolution);
9856 }
9857};
9858
9859/**
9860 * Two fingers down on a pointer mode touch pad. The width
9861 * of the two finger is larger than 1/4 of the touch pack diagnal length. However, it
9862 * is smaller than the fixed min physical length 30mm. Two fingers' distance must
9863 * be greater than the both value to be freeform gesture, so that after two
9864 * fingers start to move downwards, the gesture should be swipe.
9865 */
9866TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthSwipe) {
9867 // The min freeform gesture width is 25units/mm x 30mm = 750
9868 // which is greater than fraction of the diagnal length of the touchpad (349).
9869 // Thus, MaxSwipWidth is 750.
Harry Cutts33476232023-01-30 19:57:29 +00009870 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +00009871 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009872 NotifyMotionArgs motionArgs;
9873
9874 // Two fingers down at once.
9875 // The two fingers are 450 units apart, expects the current gesture to be PRESS
9876 // Pointer's initial position is used the [0,0] coordinate.
9877 int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125;
9878
9879 processId(mapper, FIRST_TRACKING_ID);
9880 processPosition(mapper, x1, y1);
9881 processMTSync(mapper);
9882 processId(mapper, SECOND_TRACKING_ID);
9883 processPosition(mapper, x2, y2);
9884 processMTSync(mapper);
9885 processSync(mapper);
9886
9887 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009888 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009889 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009890 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009891 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009892 ASSERT_NO_FATAL_FAILURE(
9893 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9894
9895 // It should be recognized as a SWIPE gesture when two fingers start to move down,
9896 // that there should be 1 pointer.
9897 int32_t movingDistance = 200;
9898 y1 += movingDistance;
9899 y2 += movingDistance;
9900
9901 processId(mapper, FIRST_TRACKING_ID);
9902 processPosition(mapper, x1, y1);
9903 processMTSync(mapper);
9904 processId(mapper, SECOND_TRACKING_ID);
9905 processPosition(mapper, x2, y2);
9906 processMTSync(mapper);
9907 processSync(mapper);
9908
9909 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009910 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009911 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009912 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009913 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009914 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
9915 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9916 0, 0, 0, 0));
9917}
9918
9919/**
9920 * Two fingers down on a pointer mode touch pad. The width of the two finger is larger
9921 * than the minimum freeform gesture width, 30mm. However, it is smaller than 1/4 of
9922 * the touch pack diagnal length. Two fingers' distance must be greater than the both
9923 * value to be freeform gesture, so that after two fingers start to move downwards,
9924 * the gesture should be swipe.
9925 */
9926TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthLowResolutionSwipe) {
9927 // The min freeform gesture width is 5units/mm x 30mm = 150
9928 // which is greater than fraction of the diagnal length of the touchpad (349).
9929 // Thus, MaxSwipWidth is the fraction of the diagnal length, 349.
Harry Cutts33476232023-01-30 19:57:29 +00009930 preparePointerMode(/*xResolution=*/5, /*yResolution=*/5);
Arpit Singha8c236b2023-04-25 13:56:05 +00009931 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009932 NotifyMotionArgs motionArgs;
9933
9934 // Two fingers down at once.
9935 // The two fingers are 250 units apart, expects the current gesture to be PRESS
9936 // Pointer's initial position is used the [0,0] coordinate.
9937 int32_t x1 = 100, y1 = 125, x2 = 350, y2 = 125;
9938
9939 processId(mapper, FIRST_TRACKING_ID);
9940 processPosition(mapper, x1, y1);
9941 processMTSync(mapper);
9942 processId(mapper, SECOND_TRACKING_ID);
9943 processPosition(mapper, x2, y2);
9944 processMTSync(mapper);
9945 processSync(mapper);
9946
9947 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009948 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009949 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009950 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009951 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009952 ASSERT_NO_FATAL_FAILURE(
9953 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9954
9955 // It should be recognized as a SWIPE gesture when two fingers start to move down,
9956 // and there should be 1 pointer.
9957 int32_t movingDistance = 200;
9958 y1 += movingDistance;
9959 y2 += movingDistance;
9960
9961 processId(mapper, FIRST_TRACKING_ID);
9962 processPosition(mapper, x1, y1);
9963 processMTSync(mapper);
9964 processId(mapper, SECOND_TRACKING_ID);
9965 processPosition(mapper, x2, y2);
9966 processMTSync(mapper);
9967 processSync(mapper);
9968
9969 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009970 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009971 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009972 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009973 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009974 // New coordinate is the scaled relative coordinate from the initial coordinate.
9975 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
9976 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9977 0, 0, 0, 0));
9978}
9979
9980/**
9981 * Touch the touch pad with two fingers with a distance wider than the minimum freeform
9982 * gesture width and 1/4 of the diagnal length of the touchpad. Expect to receive
9983 * freeform gestures after two fingers start to move downwards.
9984 */
9985TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthFreeform) {
Harry Cutts33476232023-01-30 19:57:29 +00009986 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +00009987 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009988
9989 NotifyMotionArgs motionArgs;
9990
9991 // Two fingers down at once. Wider than the max swipe width.
9992 // The gesture is expected to be PRESS, then transformed to FREEFORM
9993 int32_t x1 = 100, y1 = 125, x2 = 900, y2 = 125;
9994
9995 processId(mapper, FIRST_TRACKING_ID);
9996 processPosition(mapper, x1, y1);
9997 processMTSync(mapper);
9998 processId(mapper, SECOND_TRACKING_ID);
9999 processPosition(mapper, x2, y2);
10000 processMTSync(mapper);
10001 processSync(mapper);
10002
10003 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010004 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010005 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010006 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +000010007 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +000010008 // One pointer for PRESS, and its coordinate is used as the origin for pointer coordinates.
10009 ASSERT_NO_FATAL_FAILURE(
10010 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
10011
10012 int32_t movingDistance = 200;
10013
10014 // Move two fingers down, expect a cancel event because gesture is changing to freeform,
10015 // then two down events for two pointers.
10016 y1 += movingDistance;
10017 y2 += movingDistance;
10018
10019 processId(mapper, FIRST_TRACKING_ID);
10020 processPosition(mapper, x1, y1);
10021 processMTSync(mapper);
10022 processId(mapper, SECOND_TRACKING_ID);
10023 processPosition(mapper, x2, y2);
10024 processMTSync(mapper);
10025 processSync(mapper);
10026
10027 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
10028 // The previous PRESS gesture is cancelled, because it is transformed to freeform
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010029 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010030 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
10031 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010032 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010033 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010034 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
10035 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010036 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +000010037 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010038 ASSERT_EQ(2U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010039 ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN, motionArgs.action & AMOTION_EVENT_ACTION_MASK);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010040 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +000010041 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +000010042 // Two pointers' scaled relative coordinates from their initial centroid.
10043 // Initial y coordinates are 0 as y1 and y2 have the same value.
10044 float cookedX1 = (x1 - x2) / 2 * mPointerXZoomScale;
10045 float cookedX2 = (x2 - x1) / 2 * mPointerXZoomScale;
10046 // When pointers move, the new coordinates equal to the initial coordinates plus
10047 // scaled moving distance.
10048 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
10049 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
10050 0, 0, 0, 0));
10051 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], cookedX2,
10052 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
10053 0, 0, 0, 0));
10054
10055 // Move two fingers down again, expect one MOVE motion event.
10056 y1 += movingDistance;
10057 y2 += movingDistance;
10058
10059 processId(mapper, FIRST_TRACKING_ID);
10060 processPosition(mapper, x1, y1);
10061 processMTSync(mapper);
10062 processId(mapper, SECOND_TRACKING_ID);
10063 processPosition(mapper, x2, y2);
10064 processMTSync(mapper);
10065 processSync(mapper);
10066
10067 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010068 ASSERT_EQ(2U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010069 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010070 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +000010071 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +000010072 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
10073 movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
10074 0, 0, 0, 0, 0));
10075 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], cookedX2,
10076 movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
10077 0, 0, 0, 0, 0));
10078}
10079
Harry Cutts39b7ca22022-10-05 15:55:48 +000010080TEST_F(MultiTouchPointerModeTest, TwoFingerSwipeOffsets) {
Harry Cutts33476232023-01-30 19:57:29 +000010081 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +000010082 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Harry Cutts39b7ca22022-10-05 15:55:48 +000010083 NotifyMotionArgs motionArgs;
10084
10085 // Place two fingers down.
10086 int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125;
10087
10088 processId(mapper, FIRST_TRACKING_ID);
10089 processPosition(mapper, x1, y1);
10090 processMTSync(mapper);
10091 processId(mapper, SECOND_TRACKING_ID);
10092 processPosition(mapper, x2, y2);
10093 processMTSync(mapper);
10094 processSync(mapper);
10095
10096 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010097 ASSERT_EQ(1U, motionArgs.getPointerCount());
Harry Cutts39b7ca22022-10-05 15:55:48 +000010098 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
10099 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
10100 ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET));
10101 ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET));
10102
10103 // Move the two fingers down and to the left.
10104 int32_t movingDistance = 200;
10105 x1 -= movingDistance;
10106 y1 += movingDistance;
10107 x2 -= movingDistance;
10108 y2 += movingDistance;
10109
10110 processId(mapper, FIRST_TRACKING_ID);
10111 processPosition(mapper, x1, y1);
10112 processMTSync(mapper);
10113 processId(mapper, SECOND_TRACKING_ID);
10114 processPosition(mapper, x2, y2);
10115 processMTSync(mapper);
10116 processSync(mapper);
10117
10118 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010119 ASSERT_EQ(1U, motionArgs.getPointerCount());
Harry Cutts39b7ca22022-10-05 15:55:48 +000010120 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
10121 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
10122 ASSERT_LT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET), 0);
10123 ASSERT_GT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET), 0);
10124}
10125
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010126TEST_F(MultiTouchPointerModeTest, WhenViewportActiveStatusChanged_PointerGestureIsReset) {
Harry Cutts33476232023-01-30 19:57:29 +000010127 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010128 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +000010129 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010130 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
10131
10132 // Start a stylus gesture.
10133 processKey(mapper, BTN_TOOL_PEN, 1);
10134 processId(mapper, FIRST_TRACKING_ID);
10135 processPosition(mapper, 100, 200);
10136 processSync(mapper);
10137 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10138 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
10139 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010140 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010141 // TODO(b/257078296): Pointer mode generates extra event.
10142 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10143 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
10144 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010145 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010146 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
10147
10148 // Make the viewport inactive. This will put the device in disabled mode, and the ongoing stylus
10149 // gesture should be disabled.
10150 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
10151 viewport->isActive = false;
10152 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +000010153 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010154 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10155 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
10156 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010157 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010158 // TODO(b/257078296): Pointer mode generates extra event.
10159 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10160 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
10161 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010162 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010163 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
10164}
10165
Arthur Hung6d5b4b22022-01-21 07:21:10 +000010166// --- JoystickInputMapperTest ---
10167
10168class JoystickInputMapperTest : public InputMapperTest {
10169protected:
10170 static const int32_t RAW_X_MIN;
10171 static const int32_t RAW_X_MAX;
10172 static const int32_t RAW_Y_MIN;
10173 static const int32_t RAW_Y_MAX;
10174
10175 void SetUp() override {
10176 InputMapperTest::SetUp(InputDeviceClass::JOYSTICK | InputDeviceClass::EXTERNAL);
10177 }
10178 void prepareAxes() {
10179 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
10180 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
10181 }
10182
10183 void processAxis(JoystickInputMapper& mapper, int32_t axis, int32_t value) {
10184 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, axis, value);
10185 }
10186
10187 void processSync(JoystickInputMapper& mapper) {
10188 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
10189 }
10190
Michael Wrighta9cf4192022-12-01 23:46:39 +000010191 void prepareVirtualDisplay(ui::Rotation orientation) {
Arthur Hung6d5b4b22022-01-21 07:21:10 +000010192 setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH,
10193 VIRTUAL_DISPLAY_HEIGHT, orientation, VIRTUAL_DISPLAY_UNIQUE_ID,
10194 NO_PORT, ViewportType::VIRTUAL);
10195 }
10196};
10197
10198const int32_t JoystickInputMapperTest::RAW_X_MIN = -32767;
10199const int32_t JoystickInputMapperTest::RAW_X_MAX = 32767;
10200const int32_t JoystickInputMapperTest::RAW_Y_MIN = -32767;
10201const int32_t JoystickInputMapperTest::RAW_Y_MAX = 32767;
10202
10203TEST_F(JoystickInputMapperTest, Configure_AssignsDisplayUniqueId) {
10204 prepareAxes();
Arpit Singhae876352023-04-26 14:16:50 +000010205 JoystickInputMapper& mapper = constructAndAddMapper<JoystickInputMapper>();
Arthur Hung6d5b4b22022-01-21 07:21:10 +000010206
10207 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID);
10208
Michael Wrighta9cf4192022-12-01 23:46:39 +000010209 prepareVirtualDisplay(ui::ROTATION_0);
Arthur Hung6d5b4b22022-01-21 07:21:10 +000010210
10211 // Send an axis event
10212 processAxis(mapper, ABS_X, 100);
10213 processSync(mapper);
10214
10215 NotifyMotionArgs args;
10216 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
10217 ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId);
10218
10219 // Send another axis event
10220 processAxis(mapper, ABS_Y, 100);
10221 processSync(mapper);
10222
10223 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
10224 ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId);
10225}
10226
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010227// --- PeripheralControllerTest ---
Chris Yee2b1e5c2021-03-10 22:45:12 -080010228
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010229class PeripheralControllerTest : public testing::Test {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010230protected:
10231 static const char* DEVICE_NAME;
10232 static const char* DEVICE_LOCATION;
10233 static const int32_t DEVICE_ID;
10234 static const int32_t DEVICE_GENERATION;
10235 static const int32_t DEVICE_CONTROLLER_NUMBER;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010236 static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010237 static const int32_t EVENTHUB_ID;
10238
10239 std::shared_ptr<FakeEventHub> mFakeEventHub;
10240 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010241 std::unique_ptr<TestInputListener> mFakeListener;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010242 std::unique_ptr<InstrumentedInputReader> mReader;
10243 std::shared_ptr<InputDevice> mDevice;
10244
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010245 virtual void SetUp(ftl::Flags<InputDeviceClass> classes) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010246 mFakeEventHub = std::make_unique<FakeEventHub>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010247 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010248 mFakeListener = std::make_unique<TestInputListener>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010249 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010250 *mFakeListener);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010251 mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes);
10252 }
10253
10254 void SetUp() override { SetUp(DEVICE_CLASSES); }
10255
10256 void TearDown() override {
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010257 mFakeListener.reset();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010258 mFakePolicy.clear();
10259 }
10260
Chris Yee2b1e5c2021-03-10 22:45:12 -080010261 std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
10262 const std::string& location, int32_t eventHubId,
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010263 ftl::Flags<InputDeviceClass> classes) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010264 InputDeviceIdentifier identifier;
10265 identifier.name = name;
10266 identifier.location = location;
10267 std::shared_ptr<InputDevice> device =
10268 std::make_shared<InputDevice>(mReader->getContext(), deviceId, DEVICE_GENERATION,
10269 identifier);
10270 mReader->pushNextDevice(device);
10271 mFakeEventHub->addDevice(eventHubId, name, classes);
10272 mReader->loopOnce();
10273 return device;
10274 }
10275
10276 template <class T, typename... Args>
10277 T& addControllerAndConfigure(Args... args) {
10278 T& controller = mDevice->addController<T>(EVENTHUB_ID, args...);
10279
10280 return controller;
10281 }
10282};
10283
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010284const char* PeripheralControllerTest::DEVICE_NAME = "device";
10285const char* PeripheralControllerTest::DEVICE_LOCATION = "BLUETOOTH";
10286const int32_t PeripheralControllerTest::DEVICE_ID = END_RESERVED_ID + 1000;
10287const int32_t PeripheralControllerTest::DEVICE_GENERATION = 2;
10288const int32_t PeripheralControllerTest::DEVICE_CONTROLLER_NUMBER = 0;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010289const ftl::Flags<InputDeviceClass> PeripheralControllerTest::DEVICE_CLASSES =
10290 ftl::Flags<InputDeviceClass>(0); // not needed for current tests
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010291const int32_t PeripheralControllerTest::EVENTHUB_ID = 1;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010292
10293// --- BatteryControllerTest ---
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010294class BatteryControllerTest : public PeripheralControllerTest {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010295protected:
10296 void SetUp() override {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010297 PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::BATTERY);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010298 }
10299};
10300
10301TEST_F(BatteryControllerTest, GetBatteryCapacity) {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010302 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010303
Harry Cuttsa5b71292022-11-28 12:56:17 +000010304 ASSERT_TRUE(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY));
10305 ASSERT_EQ(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY).value_or(-1),
10306 FakeEventHub::BATTERY_CAPACITY);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010307}
10308
10309TEST_F(BatteryControllerTest, GetBatteryStatus) {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010310 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010311
Harry Cuttsa5b71292022-11-28 12:56:17 +000010312 ASSERT_TRUE(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY));
10313 ASSERT_EQ(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY).value_or(-1),
10314 FakeEventHub::BATTERY_STATUS);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010315}
10316
10317// --- LightControllerTest ---
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010318class LightControllerTest : public PeripheralControllerTest {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010319protected:
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010320 void SetUp() override {
10321 PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::LIGHT);
10322 }
Chris Yee2b1e5c2021-03-10 22:45:12 -080010323};
10324
Chris Ye85758332021-05-16 23:05:17 -070010325TEST_F(LightControllerTest, MonoLight) {
10326 RawLightInfo infoMono = {.id = 1,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010327 .name = "mono_light",
Chris Ye85758332021-05-16 23:05:17 -070010328 .maxBrightness = 255,
10329 .flags = InputLightClass::BRIGHTNESS,
10330 .path = ""};
10331 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010332
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010333 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010334 InputDeviceInfo info;
10335 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010336 std::vector<InputDeviceLightInfo> lights = info.getLights();
10337 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010338 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10339 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10340
10341 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_BRIGHTNESS));
10342 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_BRIGHTNESS);
10343}
10344
DingYong99f2c3c2023-12-20 15:46:06 +080010345TEST_F(LightControllerTest, MonoKeyboardMuteLight) {
10346 RawLightInfo infoMono = {.id = 1,
10347 .name = "mono_keyboard_mute",
10348 .maxBrightness = 255,
10349 .flags = InputLightClass::BRIGHTNESS |
10350 InputLightClass::KEYBOARD_MIC_MUTE,
10351 .path = ""};
10352 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10353
10354 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10355 std::list<NotifyArgs> unused =
10356 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10357 /*changes=*/{});
10358
10359 InputDeviceInfo info;
10360 controller.populateDeviceInfo(&info);
10361 std::vector<InputDeviceLightInfo> lights = info.getLights();
10362 ASSERT_EQ(1U, lights.size());
10363 ASSERT_EQ(InputDeviceLightType::KEYBOARD_MIC_MUTE, lights[0].type);
10364 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10365}
10366
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010367TEST_F(LightControllerTest, MonoKeyboardBacklight) {
10368 RawLightInfo infoMono = {.id = 1,
10369 .name = "mono_keyboard_backlight",
10370 .maxBrightness = 255,
10371 .flags = InputLightClass::BRIGHTNESS |
10372 InputLightClass::KEYBOARD_BACKLIGHT,
10373 .path = ""};
10374 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10375
10376 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10377 InputDeviceInfo info;
10378 controller.populateDeviceInfo(&info);
10379 std::vector<InputDeviceLightInfo> lights = info.getLights();
10380 ASSERT_EQ(1U, lights.size());
10381 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10382 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010383
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010384 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_BRIGHTNESS));
10385 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_BRIGHTNESS);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010386}
10387
Vaibhav Devmurari16c24192023-05-04 15:20:12 +000010388TEST_F(LightControllerTest, Ignore_MonoLight_WithPreferredBacklightLevels) {
10389 RawLightInfo infoMono = {.id = 1,
10390 .name = "mono_light",
10391 .maxBrightness = 255,
10392 .flags = InputLightClass::BRIGHTNESS,
10393 .path = ""};
10394 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10395 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10396 "0,100,200");
10397
10398 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10399 std::list<NotifyArgs> unused =
10400 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10401 /*changes=*/{});
10402
10403 InputDeviceInfo info;
10404 controller.populateDeviceInfo(&info);
10405 std::vector<InputDeviceLightInfo> lights = info.getLights();
10406 ASSERT_EQ(1U, lights.size());
10407 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10408}
10409
10410TEST_F(LightControllerTest, KeyboardBacklight_WithNoPreferredBacklightLevels) {
10411 RawLightInfo infoMono = {.id = 1,
10412 .name = "mono_keyboard_backlight",
10413 .maxBrightness = 255,
10414 .flags = InputLightClass::BRIGHTNESS |
10415 InputLightClass::KEYBOARD_BACKLIGHT,
10416 .path = ""};
10417 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10418
10419 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10420 std::list<NotifyArgs> unused =
10421 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10422 /*changes=*/{});
10423
10424 InputDeviceInfo info;
10425 controller.populateDeviceInfo(&info);
10426 std::vector<InputDeviceLightInfo> lights = info.getLights();
10427 ASSERT_EQ(1U, lights.size());
10428 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10429}
10430
10431TEST_F(LightControllerTest, KeyboardBacklight_WithPreferredBacklightLevels) {
10432 RawLightInfo infoMono = {.id = 1,
10433 .name = "mono_keyboard_backlight",
10434 .maxBrightness = 255,
10435 .flags = InputLightClass::BRIGHTNESS |
10436 InputLightClass::KEYBOARD_BACKLIGHT,
10437 .path = ""};
10438 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10439 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10440 "0,100,200");
10441
10442 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10443 std::list<NotifyArgs> unused =
10444 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10445 /*changes=*/{});
10446
10447 InputDeviceInfo info;
10448 controller.populateDeviceInfo(&info);
10449 std::vector<InputDeviceLightInfo> lights = info.getLights();
10450 ASSERT_EQ(1U, lights.size());
10451 ASSERT_EQ(3U, lights[0].preferredBrightnessLevels.size());
10452 std::set<BrightnessLevel>::iterator it = lights[0].preferredBrightnessLevels.begin();
10453 ASSERT_EQ(BrightnessLevel(0), *it);
10454 std::advance(it, 1);
10455 ASSERT_EQ(BrightnessLevel(100), *it);
10456 std::advance(it, 1);
10457 ASSERT_EQ(BrightnessLevel(200), *it);
10458}
10459
10460TEST_F(LightControllerTest, KeyboardBacklight_WithWrongPreferredBacklightLevels) {
10461 RawLightInfo infoMono = {.id = 1,
10462 .name = "mono_keyboard_backlight",
10463 .maxBrightness = 255,
10464 .flags = InputLightClass::BRIGHTNESS |
10465 InputLightClass::KEYBOARD_BACKLIGHT,
10466 .path = ""};
10467 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10468 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10469 "0,100,200,300,400,500");
10470
10471 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10472 std::list<NotifyArgs> unused =
10473 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10474 /*changes=*/{});
10475
10476 InputDeviceInfo info;
10477 controller.populateDeviceInfo(&info);
10478 std::vector<InputDeviceLightInfo> lights = info.getLights();
10479 ASSERT_EQ(1U, lights.size());
10480 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10481}
10482
Chris Yee2b1e5c2021-03-10 22:45:12 -080010483TEST_F(LightControllerTest, RGBLight) {
10484 RawLightInfo infoRed = {.id = 1,
10485 .name = "red",
10486 .maxBrightness = 255,
10487 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED,
10488 .path = ""};
10489 RawLightInfo infoGreen = {.id = 2,
10490 .name = "green",
10491 .maxBrightness = 255,
10492 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN,
10493 .path = ""};
10494 RawLightInfo infoBlue = {.id = 3,
10495 .name = "blue",
10496 .maxBrightness = 255,
10497 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE,
10498 .path = ""};
10499 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10500 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10501 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10502
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010503 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010504 InputDeviceInfo info;
10505 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010506 std::vector<InputDeviceLightInfo> lights = info.getLights();
10507 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010508 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10509 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10510 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10511
10512 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10513 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10514}
10515
10516TEST_F(LightControllerTest, CorrectRGBKeyboardBacklight) {
10517 RawLightInfo infoRed = {.id = 1,
10518 .name = "red_keyboard_backlight",
10519 .maxBrightness = 255,
10520 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED |
10521 InputLightClass::KEYBOARD_BACKLIGHT,
10522 .path = ""};
10523 RawLightInfo infoGreen = {.id = 2,
10524 .name = "green_keyboard_backlight",
10525 .maxBrightness = 255,
10526 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN |
10527 InputLightClass::KEYBOARD_BACKLIGHT,
10528 .path = ""};
10529 RawLightInfo infoBlue = {.id = 3,
10530 .name = "blue_keyboard_backlight",
10531 .maxBrightness = 255,
10532 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE |
10533 InputLightClass::KEYBOARD_BACKLIGHT,
10534 .path = ""};
10535 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10536 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10537 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10538
10539 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10540 InputDeviceInfo info;
10541 controller.populateDeviceInfo(&info);
10542 std::vector<InputDeviceLightInfo> lights = info.getLights();
10543 ASSERT_EQ(1U, lights.size());
10544 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10545 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10546 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10547
10548 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10549 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10550}
10551
10552TEST_F(LightControllerTest, IncorrectRGBKeyboardBacklight) {
10553 RawLightInfo infoRed = {.id = 1,
10554 .name = "red",
10555 .maxBrightness = 255,
10556 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED,
10557 .path = ""};
10558 RawLightInfo infoGreen = {.id = 2,
10559 .name = "green",
10560 .maxBrightness = 255,
10561 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN,
10562 .path = ""};
10563 RawLightInfo infoBlue = {.id = 3,
10564 .name = "blue",
10565 .maxBrightness = 255,
10566 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE,
10567 .path = ""};
10568 RawLightInfo infoGlobal = {.id = 3,
10569 .name = "global_keyboard_backlight",
10570 .maxBrightness = 255,
10571 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GLOBAL |
10572 InputLightClass::KEYBOARD_BACKLIGHT,
10573 .path = ""};
10574 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10575 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10576 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10577 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoGlobal));
10578
10579 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10580 InputDeviceInfo info;
10581 controller.populateDeviceInfo(&info);
10582 std::vector<InputDeviceLightInfo> lights = info.getLights();
10583 ASSERT_EQ(1U, lights.size());
10584 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10585 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10586 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010587
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010588 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10589 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010590}
10591
10592TEST_F(LightControllerTest, MultiColorRGBLight) {
10593 RawLightInfo infoColor = {.id = 1,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010594 .name = "multi_color",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010595 .maxBrightness = 255,
10596 .flags = InputLightClass::BRIGHTNESS |
10597 InputLightClass::MULTI_INTENSITY |
10598 InputLightClass::MULTI_INDEX,
10599 .path = ""};
10600
10601 mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
10602
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010603 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010604 InputDeviceInfo info;
10605 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010606 std::vector<InputDeviceLightInfo> lights = info.getLights();
10607 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010608 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10609 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10610 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10611
10612 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10613 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10614}
10615
10616TEST_F(LightControllerTest, MultiColorRGBKeyboardBacklight) {
10617 RawLightInfo infoColor = {.id = 1,
10618 .name = "multi_color_keyboard_backlight",
10619 .maxBrightness = 255,
10620 .flags = InputLightClass::BRIGHTNESS |
10621 InputLightClass::MULTI_INTENSITY |
10622 InputLightClass::MULTI_INDEX |
10623 InputLightClass::KEYBOARD_BACKLIGHT,
10624 .path = ""};
10625
10626 mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
10627
10628 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10629 InputDeviceInfo info;
10630 controller.populateDeviceInfo(&info);
10631 std::vector<InputDeviceLightInfo> lights = info.getLights();
10632 ASSERT_EQ(1U, lights.size());
10633 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10634 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10635 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010636
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010637 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10638 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010639}
10640
Josep del Rioa1046a82023-08-24 19:57:27 +000010641TEST_F(LightControllerTest, SonyPlayerIdLight) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010642 RawLightInfo info1 = {.id = 1,
Josep del Rioa1046a82023-08-24 19:57:27 +000010643 .name = "sony1",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010644 .maxBrightness = 255,
10645 .flags = InputLightClass::BRIGHTNESS,
10646 .path = ""};
10647 RawLightInfo info2 = {.id = 2,
Josep del Rioa1046a82023-08-24 19:57:27 +000010648 .name = "sony2",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010649 .maxBrightness = 255,
10650 .flags = InputLightClass::BRIGHTNESS,
10651 .path = ""};
10652 RawLightInfo info3 = {.id = 3,
Josep del Rioa1046a82023-08-24 19:57:27 +000010653 .name = "sony3",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010654 .maxBrightness = 255,
10655 .flags = InputLightClass::BRIGHTNESS,
10656 .path = ""};
10657 RawLightInfo info4 = {.id = 4,
Josep del Rioa1046a82023-08-24 19:57:27 +000010658 .name = "sony4",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010659 .maxBrightness = 255,
10660 .flags = InputLightClass::BRIGHTNESS,
10661 .path = ""};
10662 mFakeEventHub->addRawLightInfo(info1.id, std::move(info1));
10663 mFakeEventHub->addRawLightInfo(info2.id, std::move(info2));
10664 mFakeEventHub->addRawLightInfo(info3.id, std::move(info3));
10665 mFakeEventHub->addRawLightInfo(info4.id, std::move(info4));
10666
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010667 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010668 InputDeviceInfo info;
10669 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010670 std::vector<InputDeviceLightInfo> lights = info.getLights();
10671 ASSERT_EQ(1U, lights.size());
Josep del Rioa1046a82023-08-24 19:57:27 +000010672 ASSERT_STREQ("sony", lights[0].name.c_str());
10673 ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
10674 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10675 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10676
10677 ASSERT_FALSE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10678 ASSERT_TRUE(controller.setLightPlayerId(lights[0].id, LIGHT_PLAYER_ID));
10679 ASSERT_EQ(controller.getLightPlayerId(lights[0].id).value_or(-1), LIGHT_PLAYER_ID);
10680 ASSERT_STREQ("sony", lights[0].name.c_str());
10681}
10682
10683TEST_F(LightControllerTest, PlayerIdLight) {
10684 RawLightInfo info1 = {.id = 1,
10685 .name = "player-1",
10686 .maxBrightness = 255,
10687 .flags = InputLightClass::BRIGHTNESS,
10688 .path = ""};
10689 RawLightInfo info2 = {.id = 2,
10690 .name = "player-2",
10691 .maxBrightness = 255,
10692 .flags = InputLightClass::BRIGHTNESS,
10693 .path = ""};
10694 RawLightInfo info3 = {.id = 3,
10695 .name = "player-3",
10696 .maxBrightness = 255,
10697 .flags = InputLightClass::BRIGHTNESS,
10698 .path = ""};
10699 RawLightInfo info4 = {.id = 4,
10700 .name = "player-4",
10701 .maxBrightness = 255,
10702 .flags = InputLightClass::BRIGHTNESS,
10703 .path = ""};
10704 mFakeEventHub->addRawLightInfo(info1.id, std::move(info1));
10705 mFakeEventHub->addRawLightInfo(info2.id, std::move(info2));
10706 mFakeEventHub->addRawLightInfo(info3.id, std::move(info3));
10707 mFakeEventHub->addRawLightInfo(info4.id, std::move(info4));
10708
10709 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10710 InputDeviceInfo info;
10711 controller.populateDeviceInfo(&info);
10712 std::vector<InputDeviceLightInfo> lights = info.getLights();
10713 ASSERT_EQ(1U, lights.size());
10714 ASSERT_STREQ("player", lights[0].name.c_str());
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010715 ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010716 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10717 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010718
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010719 ASSERT_FALSE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10720 ASSERT_TRUE(controller.setLightPlayerId(lights[0].id, LIGHT_PLAYER_ID));
10721 ASSERT_EQ(controller.getLightPlayerId(lights[0].id).value_or(-1), LIGHT_PLAYER_ID);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010722}
10723
Michael Wrightd02c5b62014-02-10 15:10:22 -080010724} // namespace android