blob: e26cee4a53d45c7aee02dcedf996ad3e05d50aec [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;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070059using std::chrono_literals::operator""ms;
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -080060using std::chrono_literals::operator""s;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070061
Michael Wrightd02c5b62014-02-10 15:10:22 -080062// Arbitrary display properties.
Linnan Li13bf76a2024-05-05 19:18:02 +080063static constexpr ui::LogicalDisplayId DISPLAY_ID = ui::ADISPLAY_ID_DEFAULT;
Prabir Pradhanc13ff082022-09-08 22:03:30 +000064static const std::string DISPLAY_UNIQUE_ID = "local:1";
Linnan Li13bf76a2024-05-05 19:18:02 +080065static constexpr ui::LogicalDisplayId SECONDARY_DISPLAY_ID =
66 ui::LogicalDisplayId{DISPLAY_ID.val() + 1};
Prabir Pradhanc13ff082022-09-08 22:03:30 +000067static const std::string SECONDARY_DISPLAY_UNIQUE_ID = "local:2";
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
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700313 std::list<NotifyArgs> process(const RawEvent* rawEvent) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700314 std::scoped_lock<std::mutex> lock(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800315 mLastEvent = *rawEvent;
316 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};
525 ASSERT_NE(nonDefaultDisplayId, ui::ADISPLAY_ID_DEFAULT)
526 << "Test display ID should not be ui::ADISPLAY_ID_DEFAULT ";
Michael Wrightdde67b82020-10-27 16:09:22 +0000527
528 // Add the default display first and ensure it gets returned.
529 mFakePolicy->clearViewports();
Linnan Li13bf76a2024-05-05 19:18:02 +0800530 mFakePolicy->addDisplayViewport(ui::ADISPLAY_ID_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);
Linnan Li13bf76a2024-05-05 19:18:02 +0800540 ASSERT_EQ(ui::ADISPLAY_ID_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);
Linnan Li13bf76a2024-05-05 19:18:02 +0800548 mFakePolicy->addDisplayViewport(ui::ADISPLAY_ID_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);
Linnan Li13bf76a2024-05-05 19:18:02 +0800554 ASSERT_EQ(ui::ADISPLAY_ID_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 }
627 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
Yi Kong9b14ac62018-07-17 13:48:38 -0700761 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(nullptr));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700762
763 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());
778 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
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000963TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChanged) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800964 constexpr int32_t eventHubId = 1;
Chris Ye1b0c7342020-07-28 21:57:03 -0700965 addDevice(eventHubId, "ignored", InputDeviceClass::KEYBOARD, nullptr);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800966
967 NotifyConfigurationChangedArgs args;
968
969 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(&args));
970 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
971}
972
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000973TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800974 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700975 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000976 constexpr nsecs_t when = 0;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800977 constexpr int32_t eventHubId = 1;
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000978 constexpr nsecs_t readTime = 2;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800979 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800980 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800981 AINPUT_SOURCE_KEYBOARD, nullptr);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800982
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000983 mFakeEventHub->enqueueEvent(when, readTime, eventHubId, EV_KEY, KEY_A, 1);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000984 mReader->loopOnce();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800985 ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty());
986
987 RawEvent event;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800988 ASSERT_NO_FATAL_FAILURE(mapper.assertProcessWasCalled(&event));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000989 ASSERT_EQ(when, event.when);
990 ASSERT_EQ(readTime, event.readTime);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800991 ASSERT_EQ(eventHubId, event.deviceId);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800992 ASSERT_EQ(EV_KEY, event.type);
993 ASSERT_EQ(KEY_A, event.code);
994 ASSERT_EQ(1, event.value);
995}
996
Garfield Tan1c7bc862020-01-28 13:24:04 -0800997TEST_F(InputReaderTest, DeviceReset_RandomId) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800998 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700999 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001000 constexpr int32_t eventHubId = 1;
1001 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
Prabir Pradhan42611e02018-11-27 14:04:02 -08001002 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +00001003 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
1004 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001005 mReader->pushNextDevice(device);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001006 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Prabir Pradhan42611e02018-11-27 14:04:02 -08001007
1008 NotifyDeviceResetArgs resetArgs;
1009 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001010 int32_t prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001011
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001012 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001013 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -07001014 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tan1c7bc862020-01-28 13:24:04 -08001015 ASSERT_NE(prevId, resetArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001016 prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001017
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001018 enableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001019 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -07001020 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tan1c7bc862020-01-28 13:24:04 -08001021 ASSERT_NE(prevId, resetArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001022 prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001023
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001024 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001025 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -07001026 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tan1c7bc862020-01-28 13:24:04 -08001027 ASSERT_NE(prevId, resetArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001028 prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001029}
1030
Garfield Tan1c7bc862020-01-28 13:24:04 -08001031TEST_F(InputReaderTest, DeviceReset_GenerateIdWithInputReaderSource) {
1032 constexpr int32_t deviceId = 1;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001033 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Garfield Tan1c7bc862020-01-28 13:24:04 -08001034 constexpr int32_t eventHubId = 1;
1035 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
1036 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +00001037 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
1038 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001039 mReader->pushNextDevice(device);
Garfield Tan1c7bc862020-01-28 13:24:04 -08001040 ASSERT_NO_FATAL_FAILURE(addDevice(deviceId, "fake", deviceClass, nullptr));
1041
1042 NotifyDeviceResetArgs resetArgs;
1043 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1044 ASSERT_EQ(IdGenerator::Source::INPUT_READER, IdGenerator::getSource(resetArgs.id));
1045}
1046
Arthur Hungc23540e2018-11-29 20:42:11 +08001047TEST_F(InputReaderTest, Device_CanDispatchToDisplay) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001048 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001049 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001050 constexpr int32_t eventHubId = 1;
Arthur Hungc23540e2018-11-29 20:42:11 +08001051 const char* DEVICE_LOCATION = "USB1";
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001052 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
1053 FakeInputMapper& mapper =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001054 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
1055 AINPUT_SOURCE_TOUCHSCREEN);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001056 mReader->pushNextDevice(device);
Arthur Hungc23540e2018-11-29 20:42:11 +08001057
1058 const uint8_t hdmi1 = 1;
1059
1060 // Associated touch screen with second display.
1061 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
1062
1063 // Add default and second display.
Prabir Pradhan28efc192019-11-05 01:10:04 +00001064 mFakePolicy->clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00001065 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00001066 /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL);
Arthur Hungc23540e2018-11-29 20:42:11 +08001067 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +00001068 ui::ROTATION_0, /*isActive=*/true, "local:1", hdmi1,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01001069 ViewportType::EXTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001070 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::DISPLAY_INFO);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001071 mReader->loopOnce();
Prabir Pradhan28efc192019-11-05 01:10:04 +00001072
1073 // Add the device, and make sure all of the callbacks are triggered.
1074 // The device is added after the input port associations are processed since
1075 // we do not yet support dynamic device-to-display associations.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001076 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Prabir Pradhan2574dfa2019-10-16 16:35:07 -07001077 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled());
Prabir Pradhan28efc192019-11-05 01:10:04 +00001078 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001079 ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
Arthur Hungc23540e2018-11-29 20:42:11 +08001080
Arthur Hung2c9a3342019-07-23 14:18:59 +08001081 // Device should only dispatch to the specified display.
Arthur Hungc23540e2018-11-29 20:42:11 +08001082 ASSERT_EQ(deviceId, device->getId());
1083 ASSERT_FALSE(mReader->canDispatchToDisplay(deviceId, DISPLAY_ID));
1084 ASSERT_TRUE(mReader->canDispatchToDisplay(deviceId, SECONDARY_DISPLAY_ID));
Arthur Hung2c9a3342019-07-23 14:18:59 +08001085
1086 // Can't dispatch event from a disabled device.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001087 disableDevice(deviceId);
Prabir Pradhan28efc192019-11-05 01:10:04 +00001088 mReader->loopOnce();
Arthur Hung2c9a3342019-07-23 14:18:59 +08001089 ASSERT_FALSE(mReader->canDispatchToDisplay(deviceId, SECONDARY_DISPLAY_ID));
Arthur Hungc23540e2018-11-29 20:42:11 +08001090}
1091
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001092TEST_F(InputReaderTest, WhenEnabledChanges_AllSubdevicesAreUpdated) {
1093 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001094 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001095 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
1096 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
1097 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +00001098 device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
1099 AINPUT_SOURCE_KEYBOARD);
1100 device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
1101 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001102 mReader->pushNextDevice(device);
1103 mReader->pushNextDevice(device);
1104 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1", deviceClass, nullptr));
1105 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[1], "fake2", deviceClass, nullptr));
1106
1107 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(nullptr));
1108
1109 NotifyDeviceResetArgs resetArgs;
1110 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1111 ASSERT_EQ(deviceId, resetArgs.deviceId);
1112 ASSERT_TRUE(device->isEnabled());
1113 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
1114 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
1115
1116 disableDevice(deviceId);
1117 mReader->loopOnce();
1118
1119 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1120 ASSERT_EQ(deviceId, resetArgs.deviceId);
1121 ASSERT_FALSE(device->isEnabled());
1122 ASSERT_FALSE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
1123 ASSERT_FALSE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
1124
1125 enableDevice(deviceId);
1126 mReader->loopOnce();
1127
1128 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1129 ASSERT_EQ(deviceId, resetArgs.deviceId);
1130 ASSERT_TRUE(device->isEnabled());
1131 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
1132 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
1133}
1134
1135TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToSubdeviceMappers) {
1136 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001137 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001138 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
1139 // Add two subdevices to device
1140 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
1141 FakeInputMapper& mapperDevice1 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001142 device->addMapper<FakeInputMapper>(eventHubIds[0],
1143 mFakePolicy->getReaderConfiguration(),
1144 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001145 FakeInputMapper& mapperDevice2 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001146 device->addMapper<FakeInputMapper>(eventHubIds[1],
1147 mFakePolicy->getReaderConfiguration(),
1148 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001149 mReader->pushNextDevice(device);
1150 mReader->pushNextDevice(device);
1151 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1", deviceClass, nullptr));
1152 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[1], "fake2", deviceClass, nullptr));
1153
1154 mapperDevice1.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
1155 mapperDevice2.setKeyCodeState(AKEYCODE_B, AKEY_STATE_DOWN);
1156
1157 ASSERT_EQ(AKEY_STATE_DOWN,
1158 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_A));
1159 ASSERT_EQ(AKEY_STATE_DOWN,
1160 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_B));
1161 ASSERT_EQ(AKEY_STATE_UNKNOWN,
1162 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_C));
1163}
1164
Prabir Pradhan7e186182020-11-10 13:56:45 -08001165TEST_F(InputReaderTest, ChangingPointerCaptureNotifiesInputListener) {
1166 NotifyPointerCaptureChangedArgs args;
1167
Hiroki Sato25040232024-02-22 17:21:22 +09001168 auto request = mFakePolicy->setPointerCapture(/*window=*/sp<BBinder>::make());
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001169 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE);
Prabir Pradhan7e186182020-11-10 13:56:45 -08001170 mReader->loopOnce();
1171 mFakeListener->assertNotifyCaptureWasCalled(&args);
Hiroki Sato25040232024-02-22 17:21:22 +09001172 ASSERT_TRUE(args.request.isEnable()) << "Pointer Capture should be enabled.";
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001173 ASSERT_EQ(args.request, request) << "Pointer Capture sequence number should match.";
Prabir Pradhan7e186182020-11-10 13:56:45 -08001174
Hiroki Sato25040232024-02-22 17:21:22 +09001175 mFakePolicy->setPointerCapture(/*window=*/nullptr);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001176 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE);
Prabir Pradhan7e186182020-11-10 13:56:45 -08001177 mReader->loopOnce();
1178 mFakeListener->assertNotifyCaptureWasCalled(&args);
Hiroki Sato25040232024-02-22 17:21:22 +09001179 ASSERT_FALSE(args.request.isEnable()) << "Pointer Capture should be disabled.";
Prabir Pradhan7e186182020-11-10 13:56:45 -08001180
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001181 // Verify that the Pointer Capture state is not updated when the configuration value
Prabir Pradhan7e186182020-11-10 13:56:45 -08001182 // does not change.
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001183 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE);
Prabir Pradhan7e186182020-11-10 13:56:45 -08001184 mReader->loopOnce();
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001185 mFakeListener->assertNotifyCaptureWasNotCalled();
Prabir Pradhan7e186182020-11-10 13:56:45 -08001186}
1187
Prabir Pradhan018faea2024-05-08 21:52:54 +00001188TEST_F(InputReaderTest, GetLastUsedInputDeviceId) {
1189 constexpr int32_t FIRST_DEVICE_ID = END_RESERVED_ID + 1000;
1190 constexpr int32_t SECOND_DEVICE_ID = FIRST_DEVICE_ID + 1;
1191 FakeInputMapper& firstMapper =
1192 addDeviceWithFakeInputMapper(FIRST_DEVICE_ID, FIRST_DEVICE_ID, "first",
1193 InputDeviceClass::KEYBOARD, AINPUT_SOURCE_KEYBOARD,
1194 /*configuration=*/nullptr);
1195 FakeInputMapper& secondMapper =
1196 addDeviceWithFakeInputMapper(SECOND_DEVICE_ID, SECOND_DEVICE_ID, "second",
1197 InputDeviceClass::TOUCH_MT, AINPUT_SOURCE_STYLUS,
1198 /*configuration=*/nullptr);
1199
1200 ASSERT_EQ(ReservedInputDeviceId::INVALID_INPUT_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1201
1202 // Start a new key gesture from the first device
1203 firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
1204 .deviceId(FIRST_DEVICE_ID)
1205 .build()});
1206 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
1207 mReader->loopOnce();
1208 ASSERT_EQ(firstMapper.getDeviceId(), mReader->getLastUsedInputDeviceId());
1209
1210 // Start a new touch gesture from the second device
1211 secondMapper.setProcessResult(
1212 {MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
1213 .deviceId(SECOND_DEVICE_ID)
1214 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER))
1215 .build()});
1216 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
1217 mReader->loopOnce();
1218 ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1219
1220 // Releasing the key is not a new gesture, so it does not update the last used device
1221 firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
1222 .deviceId(FIRST_DEVICE_ID)
1223 .build()});
1224 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
1225 mReader->loopOnce();
1226 ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1227
1228 // But pressing a new key does start a new gesture
1229 firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
1230 .deviceId(FIRST_DEVICE_ID)
1231 .build()});
1232 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
1233 mReader->loopOnce();
1234 ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1235
1236 // Moving or ending a touch gesture does not update the last used device
1237 secondMapper.setProcessResult(
1238 {MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
1239 .deviceId(SECOND_DEVICE_ID)
1240 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
1241 .build()});
1242 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
1243 mReader->loopOnce();
1244 ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1245 secondMapper.setProcessResult({MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
1246 .deviceId(SECOND_DEVICE_ID)
1247 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
1248 .build()});
1249 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
1250 mReader->loopOnce();
1251 ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1252
1253 // Starting a new hover gesture updates the last used device
1254 secondMapper.setProcessResult(
1255 {MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1256 .deviceId(SECOND_DEVICE_ID)
1257 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
1258 .build()});
1259 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
1260 mReader->loopOnce();
1261 ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1262}
1263
Chris Ye87143712020-11-10 05:05:58 +00001264class FakeVibratorInputMapper : public FakeInputMapper {
1265public:
Arpit Singh8e6fb252023-04-06 11:49:17 +00001266 FakeVibratorInputMapper(InputDeviceContext& deviceContext,
1267 const InputReaderConfiguration& readerConfig, uint32_t sources)
1268 : FakeInputMapper(deviceContext, readerConfig, sources) {}
Chris Ye87143712020-11-10 05:05:58 +00001269
1270 std::vector<int32_t> getVibratorIds() override { return getDeviceContext().getVibratorIds(); }
1271};
1272
1273TEST_F(InputReaderTest, VibratorGetVibratorIds) {
1274 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001275 ftl::Flags<InputDeviceClass> deviceClass =
1276 InputDeviceClass::KEYBOARD | InputDeviceClass::VIBRATOR;
Chris Ye87143712020-11-10 05:05:58 +00001277 constexpr int32_t eventHubId = 1;
1278 const char* DEVICE_LOCATION = "BLUETOOTH";
1279 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
1280 FakeVibratorInputMapper& mapper =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001281 device->addMapper<FakeVibratorInputMapper>(eventHubId,
1282 mFakePolicy->getReaderConfiguration(),
1283 AINPUT_SOURCE_KEYBOARD);
Chris Ye87143712020-11-10 05:05:58 +00001284 mReader->pushNextDevice(device);
1285
1286 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1287 ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
1288
1289 ASSERT_EQ(mapper.getVibratorIds().size(), 2U);
1290 ASSERT_EQ(mReader->getVibratorIds(deviceId).size(), 2U);
1291}
1292
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001293// --- FakePeripheralController ---
Kim Low03ea0352020-11-06 12:45:07 -08001294
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001295class FakePeripheralController : public PeripheralControllerInterface {
Chris Yee2b1e5c2021-03-10 22:45:12 -08001296public:
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001297 FakePeripheralController(InputDeviceContext& deviceContext) : mDeviceContext(deviceContext) {}
Chris Yee2b1e5c2021-03-10 22:45:12 -08001298
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001299 ~FakePeripheralController() override {}
Chris Yee2b1e5c2021-03-10 22:45:12 -08001300
Andy Chenf9f1a022022-08-29 20:07:10 -04001301 int32_t getEventHubId() const { return getDeviceContext().getEventHubId(); }
1302
Chris Yee2b1e5c2021-03-10 22:45:12 -08001303 void populateDeviceInfo(InputDeviceInfo* deviceInfo) override {}
1304
1305 void dump(std::string& dump) override {}
1306
1307 std::optional<int32_t> getBatteryCapacity(int32_t batteryId) override {
1308 return getDeviceContext().getBatteryCapacity(batteryId);
Kim Low03ea0352020-11-06 12:45:07 -08001309 }
1310
Chris Yee2b1e5c2021-03-10 22:45:12 -08001311 std::optional<int32_t> getBatteryStatus(int32_t batteryId) override {
1312 return getDeviceContext().getBatteryStatus(batteryId);
Kim Low03ea0352020-11-06 12:45:07 -08001313 }
Chris Ye3fdbfef2021-01-06 18:45:18 -08001314
1315 bool setLightColor(int32_t lightId, int32_t color) override {
1316 getDeviceContext().setLightBrightness(lightId, color >> 24);
1317 return true;
1318 }
1319
1320 std::optional<int32_t> getLightColor(int32_t lightId) override {
1321 std::optional<int32_t> result = getDeviceContext().getLightBrightness(lightId);
1322 if (!result.has_value()) {
1323 return std::nullopt;
1324 }
1325 return result.value() << 24;
1326 }
Chris Yee2b1e5c2021-03-10 22:45:12 -08001327
1328 bool setLightPlayerId(int32_t lightId, int32_t playerId) override { return true; }
1329
1330 std::optional<int32_t> getLightPlayerId(int32_t lightId) override { return std::nullopt; }
1331
1332private:
1333 InputDeviceContext& mDeviceContext;
1334 inline int32_t getDeviceId() { return mDeviceContext.getId(); }
1335 inline InputDeviceContext& getDeviceContext() { return mDeviceContext; }
Andy Chenf9f1a022022-08-29 20:07:10 -04001336 inline InputDeviceContext& getDeviceContext() const { return mDeviceContext; }
Chris Ye3fdbfef2021-01-06 18:45:18 -08001337};
1338
Chris Yee2b1e5c2021-03-10 22:45:12 -08001339TEST_F(InputReaderTest, BatteryGetCapacity) {
1340 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001341 ftl::Flags<InputDeviceClass> deviceClass =
1342 InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
Chris Yee2b1e5c2021-03-10 22:45:12 -08001343 constexpr int32_t eventHubId = 1;
1344 const char* DEVICE_LOCATION = "BLUETOOTH";
1345 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001346 FakePeripheralController& controller =
1347 device->addController<FakePeripheralController>(eventHubId);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001348 mReader->pushNextDevice(device);
1349
1350 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1351
Harry Cuttsa5b71292022-11-28 12:56:17 +00001352 ASSERT_EQ(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY),
1353 FakeEventHub::BATTERY_CAPACITY);
1354 ASSERT_EQ(mReader->getBatteryCapacity(deviceId), FakeEventHub::BATTERY_CAPACITY);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001355}
1356
1357TEST_F(InputReaderTest, BatteryGetStatus) {
1358 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001359 ftl::Flags<InputDeviceClass> deviceClass =
1360 InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
Chris Yee2b1e5c2021-03-10 22:45:12 -08001361 constexpr int32_t eventHubId = 1;
1362 const char* DEVICE_LOCATION = "BLUETOOTH";
1363 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001364 FakePeripheralController& controller =
1365 device->addController<FakePeripheralController>(eventHubId);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001366 mReader->pushNextDevice(device);
1367
1368 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1369
Harry Cuttsa5b71292022-11-28 12:56:17 +00001370 ASSERT_EQ(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY),
1371 FakeEventHub::BATTERY_STATUS);
1372 ASSERT_EQ(mReader->getBatteryStatus(deviceId), FakeEventHub::BATTERY_STATUS);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001373}
1374
Prabir Pradhane287ecd2022-09-07 21:18:05 +00001375TEST_F(InputReaderTest, BatteryGetDevicePath) {
1376 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
1377 ftl::Flags<InputDeviceClass> deviceClass =
1378 InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
1379 constexpr int32_t eventHubId = 1;
1380 const char* DEVICE_LOCATION = "BLUETOOTH";
1381 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
1382 device->addController<FakePeripheralController>(eventHubId);
1383 mReader->pushNextDevice(device);
1384
1385 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1386
Harry Cuttsa5b71292022-11-28 12:56:17 +00001387 ASSERT_EQ(mReader->getBatteryDevicePath(deviceId), FakeEventHub::BATTERY_DEVPATH);
Prabir Pradhane287ecd2022-09-07 21:18:05 +00001388}
1389
Chris Ye3fdbfef2021-01-06 18:45:18 -08001390TEST_F(InputReaderTest, LightGetColor) {
1391 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001392 ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::LIGHT;
Chris Ye3fdbfef2021-01-06 18:45:18 -08001393 constexpr int32_t eventHubId = 1;
1394 const char* DEVICE_LOCATION = "BLUETOOTH";
1395 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001396 FakePeripheralController& controller =
1397 device->addController<FakePeripheralController>(eventHubId);
Chris Ye3fdbfef2021-01-06 18:45:18 -08001398 mReader->pushNextDevice(device);
1399 RawLightInfo info = {.id = 1,
1400 .name = "Mono",
1401 .maxBrightness = 255,
1402 .flags = InputLightClass::BRIGHTNESS,
1403 .path = ""};
Harry Cutts33476232023-01-30 19:57:29 +00001404 mFakeEventHub->addRawLightInfo(/*rawId=*/1, std::move(info));
1405 mFakeEventHub->fakeLightBrightness(/*rawId=*/1, 0x55);
Chris Ye3fdbfef2021-01-06 18:45:18 -08001406
1407 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Chris Ye3fdbfef2021-01-06 18:45:18 -08001408
Harry Cutts33476232023-01-30 19:57:29 +00001409 ASSERT_TRUE(controller.setLightColor(/*lightId=*/1, LIGHT_BRIGHTNESS));
1410 ASSERT_EQ(controller.getLightColor(/*lightId=*/1), LIGHT_BRIGHTNESS);
1411 ASSERT_TRUE(mReader->setLightColor(deviceId, /*lightId=*/1, LIGHT_BRIGHTNESS));
1412 ASSERT_EQ(mReader->getLightColor(deviceId, /*lightId=*/1), LIGHT_BRIGHTNESS);
Chris Ye3fdbfef2021-01-06 18:45:18 -08001413}
1414
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001415// --- InputReaderIntegrationTest ---
1416
1417// These tests create and interact with the InputReader only through its interface.
1418// The InputReader is started during SetUp(), which starts its processing in its own
1419// thread. The tests use linux uinput to emulate input devices.
1420// NOTE: Interacting with the physical device while these tests are running may cause
1421// the tests to fail.
1422class InputReaderIntegrationTest : public testing::Test {
1423protected:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001424 std::unique_ptr<TestInputListener> mTestListener;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001425 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001426 std::unique_ptr<InputReaderInterface> mReader;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001427
Prabir Pradhanafb7d612024-01-08 22:45:24 +00001428 constexpr static auto EVENT_HAPPENED_TIMEOUT = 2000ms;
1429 constexpr static auto EVENT_DID_NOT_HAPPEN_TIMEOUT = 30ms;
1430
Chris Yea52ade12020-08-27 16:49:20 -07001431 void SetUp() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001432#if !defined(__ANDROID__)
1433 GTEST_SKIP();
1434#endif
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001435 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001436
Arpit Singh440bf652023-08-09 09:23:43 +00001437 setupInputReader();
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001438 }
1439
Chris Yea52ade12020-08-27 16:49:20 -07001440 void TearDown() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001441#if !defined(__ANDROID__)
1442 return;
1443#endif
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001444 ASSERT_EQ(mReader->stop(), OK);
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001445 mReader.reset();
1446 mTestListener.reset();
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001447 mFakePolicy.clear();
1448 }
Prabir Pradhanda20b172022-09-26 17:01:18 +00001449
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001450 std::optional<InputDeviceInfo> waitForDevice(const std::string& deviceName) {
1451 std::chrono::time_point start = std::chrono::steady_clock::now();
1452 while (true) {
1453 const std::vector<InputDeviceInfo> inputDevices = mFakePolicy->getInputDevices();
1454 const auto& it = std::find_if(inputDevices.begin(), inputDevices.end(),
1455 [&deviceName](const InputDeviceInfo& info) {
1456 return info.getIdentifier().name == deviceName;
1457 });
1458 if (it != inputDevices.end()) {
1459 return std::make_optional(*it);
1460 }
1461 std::this_thread::sleep_for(1ms);
1462 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
1463 if (elapsed > 5s) {
1464 return {};
1465 }
1466 }
Prabir Pradhanda20b172022-09-26 17:01:18 +00001467 }
Arpit Singh440bf652023-08-09 09:23:43 +00001468
1469 void setupInputReader() {
Prabir Pradhanafb7d612024-01-08 22:45:24 +00001470 mTestListener = std::make_unique<TestInputListener>(EVENT_HAPPENED_TIMEOUT,
1471 EVENT_DID_NOT_HAPPEN_TIMEOUT);
Arpit Singh440bf652023-08-09 09:23:43 +00001472
1473 mReader = std::make_unique<InputReader>(std::make_shared<EventHub>(), mFakePolicy,
1474 *mTestListener);
1475 ASSERT_EQ(mReader->start(), OK);
1476
1477 // Since this test is run on a real device, all the input devices connected
1478 // to the test device will show up in mReader. We wait for those input devices to
1479 // show up before beginning the tests.
1480 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1481 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyInputDevicesChangedWasCalled());
1482 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
1483 }
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001484};
1485
1486TEST_F(InputReaderIntegrationTest, TestInvalidDevice) {
1487 // An invalid input device that is only used for this test.
1488 class InvalidUinputDevice : public UinputDevice {
1489 public:
Harry Cutts33476232023-01-30 19:57:29 +00001490 InvalidUinputDevice() : UinputDevice("Invalid Device", /*productId=*/99) {}
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001491
1492 private:
1493 void configureDevice(int fd, uinput_user_dev* device) override {}
1494 };
1495
1496 const size_t numDevices = mFakePolicy->getInputDevices().size();
1497
1498 // UinputDevice does not set any event or key bits, so InputReader should not
1499 // consider it as a valid device.
1500 std::unique_ptr<UinputDevice> invalidDevice = createUinputDevice<InvalidUinputDevice>();
1501 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesNotChanged());
1502 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasNotCalled());
1503 ASSERT_EQ(numDevices, mFakePolicy->getInputDevices().size());
1504
1505 invalidDevice.reset();
1506 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesNotChanged());
1507 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasNotCalled());
1508 ASSERT_EQ(numDevices, mFakePolicy->getInputDevices().size());
1509}
1510
1511TEST_F(InputReaderIntegrationTest, AddNewDevice) {
1512 const size_t initialNumDevices = mFakePolicy->getInputDevices().size();
1513
1514 std::unique_ptr<UinputHomeKey> keyboard = createUinputDevice<UinputHomeKey>();
1515 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1516 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
1517 ASSERT_EQ(initialNumDevices + 1, mFakePolicy->getInputDevices().size());
1518
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001519 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001520 ASSERT_TRUE(device.has_value());
1521 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, device->getKeyboardType());
1522 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources());
1523 ASSERT_EQ(0U, device->getMotionRanges().size());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001524
1525 keyboard.reset();
1526 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1527 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
1528 ASSERT_EQ(initialNumDevices, mFakePolicy->getInputDevices().size());
1529}
1530
1531TEST_F(InputReaderIntegrationTest, SendsEventsToInputListener) {
1532 std::unique_ptr<UinputHomeKey> keyboard = createUinputDevice<UinputHomeKey>();
1533 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1534
1535 NotifyConfigurationChangedArgs configChangedArgs;
1536 ASSERT_NO_FATAL_FAILURE(
1537 mTestListener->assertNotifyConfigurationChangedWasCalled(&configChangedArgs));
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001538 int32_t prevId = configChangedArgs.id;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001539 nsecs_t prevTimestamp = configChangedArgs.eventTime;
1540
1541 NotifyKeyArgs keyArgs;
1542 keyboard->pressAndReleaseHomeKey();
1543 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs));
1544 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
Garfield Tan1c7bc862020-01-28 13:24:04 -08001545 ASSERT_NE(prevId, keyArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001546 prevId = keyArgs.id;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001547 ASSERT_LE(prevTimestamp, keyArgs.eventTime);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001548 ASSERT_LE(keyArgs.eventTime, keyArgs.readTime);
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001549 prevTimestamp = keyArgs.eventTime;
1550
1551 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs));
1552 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
Garfield Tan1c7bc862020-01-28 13:24:04 -08001553 ASSERT_NE(prevId, keyArgs.id);
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001554 ASSERT_LE(prevTimestamp, keyArgs.eventTime);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001555 ASSERT_LE(keyArgs.eventTime, keyArgs.readTime);
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001556}
Michael Wrightd02c5b62014-02-10 15:10:22 -08001557
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001558TEST_F(InputReaderIntegrationTest, ExternalStylusesButtons) {
1559 std::unique_ptr<UinputExternalStylus> stylus = createUinputDevice<UinputExternalStylus>();
1560 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1561
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001562 const auto device = waitForDevice(stylus->getName());
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001563 ASSERT_TRUE(device.has_value());
1564
Prabir Pradhana3621852022-10-14 18:57:23 +00001565 // An external stylus with buttons should also be recognized as a keyboard.
1566 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_STYLUS, device->getSources())
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001567 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1568 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, device->getKeyboardType());
1569
1570 const auto DOWN =
1571 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD));
1572 const auto UP = AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD));
1573
1574 stylus->pressAndReleaseKey(BTN_STYLUS);
1575 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1576 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
1577 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1578 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
1579
1580 stylus->pressAndReleaseKey(BTN_STYLUS2);
1581 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1582 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_SECONDARY))));
1583 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1584 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_SECONDARY))));
1585
1586 stylus->pressAndReleaseKey(BTN_STYLUS3);
1587 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1588 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_TERTIARY))));
1589 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1590 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_TERTIARY))));
1591}
1592
Prabir Pradhan3c28b942023-08-18 20:02:01 +00001593TEST_F(InputReaderIntegrationTest, KeyboardWithStylusButtons) {
1594 std::unique_ptr<UinputKeyboard> keyboard =
1595 createUinputDevice<UinputKeyboard>("KeyboardWithStylusButtons", /*productId=*/99,
1596 std::initializer_list<int>{KEY_Q, KEY_W, KEY_E,
1597 KEY_R, KEY_T, KEY_Y,
1598 BTN_STYLUS, BTN_STYLUS2,
1599 BTN_STYLUS3});
1600 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1601
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001602 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhan3c28b942023-08-18 20:02:01 +00001603 ASSERT_TRUE(device.has_value());
1604
1605 // An alphabetical keyboard that reports stylus buttons should not be recognized as a stylus.
1606 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources())
1607 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1608 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, device->getKeyboardType());
1609}
1610
Prabir Pradhan37a819b2023-08-22 23:20:16 +00001611TEST_F(InputReaderIntegrationTest, HidUsageKeyboardIsNotAStylus) {
1612 // Create a Uinput keyboard that simulates a keyboard that can report HID usage codes. The
1613 // hid-input driver reports HID usage codes using the value for EV_MSC MSC_SCAN event.
1614 std::unique_ptr<UinputKeyboardWithHidUsage> keyboard =
1615 createUinputDevice<UinputKeyboardWithHidUsage>(
1616 std::initializer_list<int>{KEY_VOLUMEUP, KEY_VOLUMEDOWN});
1617 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1618
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001619 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhan37a819b2023-08-22 23:20:16 +00001620 ASSERT_TRUE(device.has_value());
1621
1622 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources())
1623 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1624
1625 // If a device supports reporting HID usage codes, it shouldn't automatically support
1626 // stylus keys.
1627 const std::vector<int> keycodes{AKEYCODE_STYLUS_BUTTON_PRIMARY};
1628 uint8_t outFlags[] = {0};
1629 ASSERT_TRUE(mReader->hasKeys(device->getId(), AINPUT_SOURCE_KEYBOARD, keycodes, outFlags));
1630 ASSERT_EQ(0, outFlags[0]) << "Keyboard should not have stylus button";
1631}
1632
Siarhei Vishniakoua0d2b802020-05-13 14:00:31 -07001633/**
1634 * The Steam controller sends BTN_GEAR_DOWN and BTN_GEAR_UP for the two "paddle" buttons
1635 * on the back. In this test, we make sure that BTN_GEAR_DOWN / BTN_WHEEL and BTN_GEAR_UP
1636 * are passed to the listener.
1637 */
1638static_assert(BTN_GEAR_DOWN == BTN_WHEEL);
1639TEST_F(InputReaderIntegrationTest, SendsGearDownAndUpToInputListener) {
1640 std::unique_ptr<UinputSteamController> controller = createUinputDevice<UinputSteamController>();
1641 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1642 NotifyKeyArgs keyArgs;
1643
1644 controller->pressAndReleaseKey(BTN_GEAR_DOWN);
1645 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_DOWN
1646 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_UP
1647 ASSERT_EQ(BTN_GEAR_DOWN, keyArgs.scanCode);
1648
1649 controller->pressAndReleaseKey(BTN_GEAR_UP);
1650 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_DOWN
1651 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_UP
1652 ASSERT_EQ(BTN_GEAR_UP, keyArgs.scanCode);
1653}
1654
Prabir Pradhan484d55a2022-10-14 23:17:16 +00001655// --- TouchIntegrationTest ---
1656
Arpit Singh440bf652023-08-09 09:23:43 +00001657class BaseTouchIntegrationTest : public InputReaderIntegrationTest {
Arthur Hungaab25622020-01-16 11:22:11 +08001658protected:
Arthur Hungaab25622020-01-16 11:22:11 +08001659 const std::string UNIQUE_ID = "local:0";
1660
Chris Yea52ade12020-08-27 16:49:20 -07001661 void SetUp() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001662#if !defined(__ANDROID__)
1663 GTEST_SKIP();
1664#endif
Arthur Hungaab25622020-01-16 11:22:11 +08001665 InputReaderIntegrationTest::SetUp();
1666 // At least add an internal display.
Michael Wrighta9cf4192022-12-01 23:46:39 +00001667 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
1668 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Arthur Hungaab25622020-01-16 11:22:11 +08001669
1670 mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT));
1671 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1672 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001673 const auto info = waitForDevice(mDevice->getName());
Prabir Pradhanda20b172022-09-26 17:01:18 +00001674 ASSERT_TRUE(info);
1675 mDeviceInfo = *info;
Arthur Hungaab25622020-01-16 11:22:11 +08001676 }
1677
Linnan Li13bf76a2024-05-05 19:18:02 +08001678 void setDisplayInfoAndReconfigure(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
Michael Wrighta9cf4192022-12-01 23:46:39 +00001679 ui::Rotation orientation, const std::string& uniqueId,
Arthur Hungaab25622020-01-16 11:22:11 +08001680 std::optional<uint8_t> physicalPort,
1681 ViewportType viewportType) {
Harry Cutts33476232023-01-30 19:57:29 +00001682 mFakePolicy->addDisplayViewport(displayId, width, height, orientation, /*isActive=*/true,
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00001683 uniqueId, physicalPort, viewportType);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001684 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hungaab25622020-01-16 11:22:11 +08001685 }
1686
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001687 void assertReceivedMotion(int32_t action, const std::vector<Point>& points) {
1688 NotifyMotionArgs args;
1689 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1690 EXPECT_EQ(action, args.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07001691 ASSERT_EQ(points.size(), args.getPointerCount());
1692 for (size_t i = 0; i < args.getPointerCount(); i++) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001693 EXPECT_EQ(points[i].x, args.pointerCoords[i].getX());
1694 EXPECT_EQ(points[i].y, args.pointerCoords[i].getY());
1695 }
1696 }
1697
Arthur Hungaab25622020-01-16 11:22:11 +08001698 std::unique_ptr<UinputTouchScreen> mDevice;
Prabir Pradhanda20b172022-09-26 17:01:18 +00001699 InputDeviceInfo mDeviceInfo;
Arthur Hungaab25622020-01-16 11:22:11 +08001700};
1701
Arpit Singh440bf652023-08-09 09:23:43 +00001702enum class TouchIntegrationTestDisplays { DISPLAY_INTERNAL, DISPLAY_INPUT_PORT, DISPLAY_UNIQUE_ID };
1703
1704class TouchIntegrationTest : public BaseTouchIntegrationTest,
1705 public testing::WithParamInterface<TouchIntegrationTestDisplays> {
1706protected:
1707 static constexpr std::optional<uint8_t> DISPLAY_PORT = 0;
1708 const std::string INPUT_PORT = "uinput_touch/input0";
1709
1710 void SetUp() override {
1711#if !defined(__ANDROID__)
1712 GTEST_SKIP();
1713#endif
1714 if (GetParam() == TouchIntegrationTestDisplays::DISPLAY_INTERNAL) {
1715 BaseTouchIntegrationTest::SetUp();
1716 return;
1717 }
1718
1719 // setup policy with a input-port or UniqueId association to the display
1720 bool isInputPortAssociation =
1721 GetParam() == TouchIntegrationTestDisplays::DISPLAY_INPUT_PORT;
1722
1723 mFakePolicy = sp<FakeInputReaderPolicy>::make();
1724 if (isInputPortAssociation) {
1725 mFakePolicy->addInputPortAssociation(INPUT_PORT, DISPLAY_PORT.value());
1726 } else {
1727 mFakePolicy->addInputUniqueIdAssociation(INPUT_PORT, UNIQUE_ID);
1728 }
Arpit Singh440bf652023-08-09 09:23:43 +00001729
1730 InputReaderIntegrationTest::setupInputReader();
1731
1732 mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT),
1733 INPUT_PORT);
1734 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1735
1736 // Add a display linked to a physical port or UniqueId.
1737 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
1738 UNIQUE_ID, isInputPortAssociation ? DISPLAY_PORT : NO_PORT,
1739 ViewportType::INTERNAL);
1740 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1741 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001742 const auto info = waitForDevice(mDevice->getName());
Arpit Singh440bf652023-08-09 09:23:43 +00001743 ASSERT_TRUE(info);
1744 mDeviceInfo = *info;
1745 }
1746};
1747
1748TEST_P(TouchIntegrationTest, MultiTouchDeviceSource) {
Prabir Pradhanf9a41282022-10-25 17:15:50 +00001749 // The UinputTouchScreen is an MT device that supports MT_TOOL_TYPE and also supports stylus
1750 // buttons. It should show up as a touchscreen, stylus, and keyboard (for reporting button
1751 // presses).
1752 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD,
1753 mDeviceInfo.getSources());
1754}
1755
Arpit Singh440bf652023-08-09 09:23:43 +00001756TEST_P(TouchIntegrationTest, InputEvent_ProcessSingleTouch) {
Arthur Hungaab25622020-01-16 11:22:11 +08001757 NotifyMotionArgs args;
1758 const Point centerPoint = mDevice->getCenterPoint();
1759
1760 // ACTION_DOWN
Arthur Hung9ad18942021-06-19 02:04:46 +00001761 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001762 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001763 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001764 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1765 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1766
1767 // ACTION_MOVE
1768 mDevice->sendMove(centerPoint + Point(1, 1));
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001769 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001770 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1771 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1772
1773 // ACTION_UP
1774 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001775 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001776 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1777 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
1778}
1779
Arpit Singh440bf652023-08-09 09:23:43 +00001780TEST_P(TouchIntegrationTest, InputEvent_ProcessMultiTouch) {
Arthur Hungaab25622020-01-16 11:22:11 +08001781 NotifyMotionArgs args;
1782 const Point centerPoint = mDevice->getCenterPoint();
1783
1784 // ACTION_DOWN
Arthur Hung9ad18942021-06-19 02:04:46 +00001785 mDevice->sendSlot(FIRST_SLOT);
1786 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001787 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001788 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001789 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1790 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1791
1792 // ACTION_POINTER_DOWN (Second slot)
1793 const Point secondPoint = centerPoint + Point(100, 100);
1794 mDevice->sendSlot(SECOND_SLOT);
1795 mDevice->sendTrackingId(SECOND_TRACKING_ID);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001796 mDevice->sendDown(secondPoint);
1797 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001798 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001799 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001800
1801 // ACTION_MOVE (Second slot)
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001802 mDevice->sendMove(secondPoint + Point(1, 1));
1803 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001804 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1805 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1806
1807 // ACTION_POINTER_UP (Second slot)
arthurhungcc7f9802020-04-30 17:55:40 +08001808 mDevice->sendPointerUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001809 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001810 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001811 ASSERT_EQ(ACTION_POINTER_1_UP, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001812
1813 // ACTION_UP
1814 mDevice->sendSlot(FIRST_SLOT);
1815 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001816 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001817 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1818 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
1819}
1820
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001821/**
1822 * What happens when a pointer goes up while another pointer moves in the same frame? Are POINTER_UP
1823 * events guaranteed to contain the same data as a preceding MOVE, or can they contain different
1824 * data?
1825 * In this test, we try to send a change in coordinates in Pointer 0 in the same frame as the
1826 * liftoff of Pointer 1. We check that POINTER_UP event is generated first, and the MOVE event
1827 * for Pointer 0 only is generated after.
1828 * Suppose we are only interested in learning the movement of Pointer 0. If we only observe MOVE
1829 * events, we will not miss any information.
1830 * Even though the Pointer 1 up event contains updated Pointer 0 coordinates, there is another MOVE
1831 * event generated afterwards that contains the newest movement of pointer 0.
1832 * This is important for palm rejection. If there is a subsequent InputListener stage that detects
1833 * palms, and wants to cancel Pointer 1, then it is safe to simply drop POINTER_1_UP event without
1834 * losing information about non-palm pointers.
1835 */
Arpit Singh440bf652023-08-09 09:23:43 +00001836TEST_P(TouchIntegrationTest, MultiTouch_PointerMoveAndSecondPointerUp) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001837 NotifyMotionArgs args;
1838 const Point centerPoint = mDevice->getCenterPoint();
1839
1840 // ACTION_DOWN
1841 mDevice->sendSlot(FIRST_SLOT);
1842 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1843 mDevice->sendDown(centerPoint);
1844 mDevice->sendSync();
1845 assertReceivedMotion(AMOTION_EVENT_ACTION_DOWN, {centerPoint});
1846
1847 // ACTION_POINTER_DOWN (Second slot)
1848 const Point secondPoint = centerPoint + Point(100, 100);
1849 mDevice->sendSlot(SECOND_SLOT);
1850 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1851 mDevice->sendDown(secondPoint);
1852 mDevice->sendSync();
1853 assertReceivedMotion(ACTION_POINTER_1_DOWN, {centerPoint, secondPoint});
1854
1855 // ACTION_MOVE (First slot)
1856 mDevice->sendSlot(FIRST_SLOT);
1857 mDevice->sendMove(centerPoint + Point(5, 5));
1858 // ACTION_POINTER_UP (Second slot)
1859 mDevice->sendSlot(SECOND_SLOT);
1860 mDevice->sendPointerUp();
1861 // Send a single sync for the above 2 pointer updates
1862 mDevice->sendSync();
1863
1864 // First, we should get POINTER_UP for the second pointer
1865 assertReceivedMotion(ACTION_POINTER_1_UP,
1866 {/*first pointer */ centerPoint + Point(5, 5),
1867 /*second pointer*/ secondPoint});
1868
1869 // Next, the MOVE event for the first pointer
1870 assertReceivedMotion(AMOTION_EVENT_ACTION_MOVE, {centerPoint + Point(5, 5)});
1871}
1872
1873/**
1874 * Similar scenario as above. The difference is that when the second pointer goes up, it will first
1875 * move, and then it will go up, all in the same frame.
1876 * In this scenario, the movement of the second pointer just prior to liftoff is ignored, and never
1877 * gets sent to the listener.
1878 */
Arpit Singh440bf652023-08-09 09:23:43 +00001879TEST_P(TouchIntegrationTest, MultiTouch_PointerMoveAndSecondPointerMoveAndUp) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001880 NotifyMotionArgs args;
1881 const Point centerPoint = mDevice->getCenterPoint();
1882
1883 // ACTION_DOWN
1884 mDevice->sendSlot(FIRST_SLOT);
1885 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1886 mDevice->sendDown(centerPoint);
1887 mDevice->sendSync();
1888 assertReceivedMotion(AMOTION_EVENT_ACTION_DOWN, {centerPoint});
1889
1890 // ACTION_POINTER_DOWN (Second slot)
1891 const Point secondPoint = centerPoint + Point(100, 100);
1892 mDevice->sendSlot(SECOND_SLOT);
1893 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1894 mDevice->sendDown(secondPoint);
1895 mDevice->sendSync();
1896 assertReceivedMotion(ACTION_POINTER_1_DOWN, {centerPoint, secondPoint});
1897
1898 // ACTION_MOVE (First slot)
1899 mDevice->sendSlot(FIRST_SLOT);
1900 mDevice->sendMove(centerPoint + Point(5, 5));
1901 // ACTION_POINTER_UP (Second slot)
1902 mDevice->sendSlot(SECOND_SLOT);
1903 mDevice->sendMove(secondPoint + Point(6, 6));
1904 mDevice->sendPointerUp();
1905 // Send a single sync for the above 2 pointer updates
1906 mDevice->sendSync();
1907
1908 // First, we should get POINTER_UP for the second pointer
1909 // The movement of the second pointer during the liftoff frame is ignored.
1910 // The coordinates 'secondPoint + Point(6, 6)' are never sent to the listener.
1911 assertReceivedMotion(ACTION_POINTER_1_UP,
1912 {/*first pointer */ centerPoint + Point(5, 5),
1913 /*second pointer*/ secondPoint});
1914
1915 // Next, the MOVE event for the first pointer
1916 assertReceivedMotion(AMOTION_EVENT_ACTION_MOVE, {centerPoint + Point(5, 5)});
1917}
1918
Arpit Singh440bf652023-08-09 09:23:43 +00001919TEST_P(TouchIntegrationTest, InputEvent_ProcessPalm) {
Arthur Hungaab25622020-01-16 11:22:11 +08001920 NotifyMotionArgs args;
1921 const Point centerPoint = mDevice->getCenterPoint();
1922
1923 // ACTION_DOWN
arthurhungcc7f9802020-04-30 17:55:40 +08001924 mDevice->sendSlot(FIRST_SLOT);
1925 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001926 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001927 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001928 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1929 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1930
arthurhungcc7f9802020-04-30 17:55:40 +08001931 // ACTION_POINTER_DOWN (second slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001932 const Point secondPoint = centerPoint + Point(100, 100);
1933 mDevice->sendSlot(SECOND_SLOT);
1934 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1935 mDevice->sendDown(secondPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001936 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001937 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001938 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001939
arthurhungcc7f9802020-04-30 17:55:40 +08001940 // ACTION_MOVE (second slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001941 mDevice->sendMove(secondPoint + Point(1, 1));
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001942 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001943 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1944 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1945
arthurhungcc7f9802020-04-30 17:55:40 +08001946 // Send MT_TOOL_PALM (second slot), which indicates that the touch IC has determined this to be
1947 // a palm event.
1948 // Expect to receive the ACTION_POINTER_UP with cancel flag.
Arthur Hungaab25622020-01-16 11:22:11 +08001949 mDevice->sendToolType(MT_TOOL_PALM);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001950 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001951 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001952 ASSERT_EQ(ACTION_POINTER_1_UP, args.action);
arthurhungcc7f9802020-04-30 17:55:40 +08001953 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, args.flags);
Arthur Hungaab25622020-01-16 11:22:11 +08001954
arthurhungcc7f9802020-04-30 17:55:40 +08001955 // Send up to second slot, expect first slot send moving.
1956 mDevice->sendPointerUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001957 mDevice->sendSync();
arthurhungcc7f9802020-04-30 17:55:40 +08001958 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1959 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001960
arthurhungcc7f9802020-04-30 17:55:40 +08001961 // Send ACTION_UP (first slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001962 mDevice->sendSlot(FIRST_SLOT);
1963 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001964 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001965
arthurhungcc7f9802020-04-30 17:55:40 +08001966 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1967 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001968}
1969
Prabir Pradhanc09ec6d2023-08-14 22:31:43 +00001970/**
1971 * Some drivers historically have reported axis values outside of the range specified in the
1972 * evdev axis info. Ensure we don't crash when this happens. For example, a driver may report a
1973 * pressure value greater than the reported maximum, since it unclear what specific meaning the
1974 * maximum value for pressure has (beyond the maximum value that can be produced by a sensor),
1975 * and no units for pressure (resolution) is specified by the evdev documentation.
1976 */
1977TEST_P(TouchIntegrationTest, AcceptsAxisValuesOutsideReportedRange) {
1978 const Point centerPoint = mDevice->getCenterPoint();
1979
1980 // Down with pressure outside the reported range
1981 mDevice->sendSlot(FIRST_SLOT);
1982 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1983 mDevice->sendDown(centerPoint);
1984 mDevice->sendPressure(UinputTouchScreen::RAW_PRESSURE_MAX + 2);
1985 mDevice->sendSync();
1986 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1987 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
1988
1989 // Move to a point outside the reported range
1990 mDevice->sendMove(Point(DISPLAY_WIDTH, DISPLAY_HEIGHT) + Point(1, 1));
1991 mDevice->sendSync();
1992 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1993 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
1994
1995 // Up
1996 mDevice->sendUp();
1997 mDevice->sendSync();
1998 ASSERT_NO_FATAL_FAILURE(
1999 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2000}
2001
Arpit Singh440bf652023-08-09 09:23:43 +00002002TEST_P(TouchIntegrationTest, NotifiesPolicyWhenStylusGestureStarted) {
Prabir Pradhanda20b172022-09-26 17:01:18 +00002003 const Point centerPoint = mDevice->getCenterPoint();
2004
2005 // Send down with the pen tool selected. The policy should be notified of the stylus presence.
2006 mDevice->sendSlot(FIRST_SLOT);
2007 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2008 mDevice->sendToolType(MT_TOOL_PEN);
2009 mDevice->sendDown(centerPoint);
2010 mDevice->sendSync();
2011 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2012 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002013 WithToolType(ToolType::STYLUS))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00002014
2015 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotified(mDeviceInfo.getId()));
2016
2017 // Release the stylus touch.
2018 mDevice->sendUp();
2019 mDevice->sendSync();
2020 ASSERT_NO_FATAL_FAILURE(
2021 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2022
2023 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotNotified());
2024
2025 // Touch down with the finger, without the pen tool selected. The policy is not notified.
2026 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2027 mDevice->sendToolType(MT_TOOL_FINGER);
2028 mDevice->sendDown(centerPoint);
2029 mDevice->sendSync();
2030 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2031 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002032 WithToolType(ToolType::FINGER))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00002033
2034 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotNotified());
2035
2036 mDevice->sendUp();
2037 mDevice->sendSync();
2038 ASSERT_NO_FATAL_FAILURE(
2039 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2040
2041 // Send a move event with the stylus tool without BTN_TOUCH to generate a hover enter.
2042 // The policy should be notified of the stylus presence.
2043 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2044 mDevice->sendToolType(MT_TOOL_PEN);
2045 mDevice->sendMove(centerPoint);
2046 mDevice->sendSync();
2047 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2048 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002049 WithToolType(ToolType::STYLUS))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00002050
2051 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotified(mDeviceInfo.getId()));
2052}
2053
Arpit Singh440bf652023-08-09 09:23:43 +00002054TEST_P(TouchIntegrationTest, ExternalStylusConnectedDuringTouchGesture) {
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002055 const Point centerPoint = mDevice->getCenterPoint();
2056
2057 // Down
2058 mDevice->sendSlot(FIRST_SLOT);
2059 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2060 mDevice->sendDown(centerPoint);
2061 mDevice->sendSync();
2062 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2063 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
2064
2065 // Move
2066 mDevice->sendMove(centerPoint + Point(1, 1));
2067 mDevice->sendSync();
2068 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2069 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
2070
2071 // Connecting an external stylus mid-gesture should not interrupt the ongoing gesture stream.
2072 auto externalStylus = createUinputDevice<UinputExternalStylus>();
2073 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
2074 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002075 const auto stylusInfo = waitForDevice(externalStylus->getName());
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002076 ASSERT_TRUE(stylusInfo);
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002077
2078 // Move
2079 mDevice->sendMove(centerPoint + Point(2, 2));
2080 mDevice->sendSync();
2081 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2082 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
2083
2084 // Disconnecting an external stylus mid-gesture should not interrupt the ongoing gesture stream.
2085 externalStylus.reset();
2086 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
2087 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
2088 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2089
2090 // Up
2091 mDevice->sendUp();
2092 mDevice->sendSync();
2093 ASSERT_NO_FATAL_FAILURE(
2094 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2095
2096 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2097}
2098
Arpit Singh440bf652023-08-09 09:23:43 +00002099INSTANTIATE_TEST_SUITE_P(TouchIntegrationTestDisplayVariants, TouchIntegrationTest,
2100 testing::Values(TouchIntegrationTestDisplays::DISPLAY_INTERNAL,
2101 TouchIntegrationTestDisplays::DISPLAY_INPUT_PORT,
2102 TouchIntegrationTestDisplays::DISPLAY_UNIQUE_ID));
2103
Prabir Pradhan124ea442022-10-28 20:27:44 +00002104// --- StylusButtonIntegrationTest ---
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002105
Prabir Pradhan124ea442022-10-28 20:27:44 +00002106// Verify the behavior of button presses reported by various kinds of styluses, including buttons
2107// reported by the touchscreen's device, by a fused external stylus, and by an un-fused external
2108// stylus.
2109template <typename UinputStylusDevice>
Arpit Singh440bf652023-08-09 09:23:43 +00002110class StylusButtonIntegrationTest : public BaseTouchIntegrationTest {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002111protected:
2112 void SetUp() override {
2113#if !defined(__ANDROID__)
2114 GTEST_SKIP();
2115#endif
Arpit Singh440bf652023-08-09 09:23:43 +00002116 BaseTouchIntegrationTest::SetUp();
Prabir Pradhan124ea442022-10-28 20:27:44 +00002117 mTouchscreen = mDevice.get();
2118 mTouchscreenInfo = mDeviceInfo;
2119
2120 setUpStylusDevice();
2121 }
2122
2123 UinputStylusDevice* mStylus{nullptr};
2124 InputDeviceInfo mStylusInfo{};
2125
2126 UinputTouchScreen* mTouchscreen{nullptr};
2127 InputDeviceInfo mTouchscreenInfo{};
2128
2129private:
2130 // When we are attempting to test stylus button events that are sent from the touchscreen,
2131 // use the same Uinput device for the touchscreen and the stylus.
2132 template <typename T = UinputStylusDevice>
2133 std::enable_if_t<std::is_same_v<UinputTouchScreen, T>, void> setUpStylusDevice() {
2134 mStylus = mDevice.get();
2135 mStylusInfo = mDeviceInfo;
2136 }
2137
2138 // When we are attempting to stylus buttons from an external stylus being merged with touches
2139 // from a touchscreen, create a new Uinput device through which stylus buttons can be injected.
2140 template <typename T = UinputStylusDevice>
2141 std::enable_if_t<!std::is_same_v<UinputTouchScreen, T>, void> setUpStylusDevice() {
2142 mStylusDeviceLifecycleTracker = createUinputDevice<T>();
2143 mStylus = mStylusDeviceLifecycleTracker.get();
2144 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
2145 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002146 const auto info = waitForDevice(mStylus->getName());
Prabir Pradhan124ea442022-10-28 20:27:44 +00002147 ASSERT_TRUE(info);
2148 mStylusInfo = *info;
2149 }
2150
2151 std::unique_ptr<UinputStylusDevice> mStylusDeviceLifecycleTracker{};
2152
2153 // Hide the base class's device to expose it with a different name for readability.
Arpit Singh440bf652023-08-09 09:23:43 +00002154 using BaseTouchIntegrationTest::mDevice;
2155 using BaseTouchIntegrationTest::mDeviceInfo;
Prabir Pradhan124ea442022-10-28 20:27:44 +00002156};
2157
2158using StylusButtonIntegrationTestTypes =
2159 ::testing::Types<UinputTouchScreen, UinputExternalStylus, UinputExternalStylusWithPressure>;
2160TYPED_TEST_SUITE(StylusButtonIntegrationTest, StylusButtonIntegrationTestTypes);
2161
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002162TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsGenerateKeyEvents) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002163 const auto stylusId = TestFixture::mStylusInfo.getId();
2164
2165 TestFixture::mStylus->pressKey(BTN_STYLUS);
2166 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2167 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2168 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2169
2170 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2171 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002172 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002173 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002174}
2175
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002176TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingTouchGesture) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002177 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2178 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2179 const auto stylusId = TestFixture::mStylusInfo.getId();
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002180
2181 // Press the stylus button.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002182 TestFixture::mStylus->pressKey(BTN_STYLUS);
2183 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002184 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002185 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002186
2187 // Start and finish a stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002188 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2189 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2190 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2191 TestFixture::mTouchscreen->sendDown(centerPoint);
2192 TestFixture::mTouchscreen->sendSync();
2193 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002194 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002195 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002196 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2197 WithDeviceId(touchscreenId))));
2198 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002199 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
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))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002203
Prabir Pradhan124ea442022-10-28 20:27:44 +00002204 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2205 TestFixture::mTouchscreen->sendSync();
2206 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002207 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002208 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002209 WithDeviceId(touchscreenId))));
2210 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002211 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002212 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002213 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002214
2215 // Release the stylus button.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002216 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2217 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002218 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002219 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002220}
2221
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002222TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingHoveringTouchGesture) {
Prabir Pradhan9a561c22022-11-07 16:11:23 +00002223 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2224 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2225 const auto stylusId = TestFixture::mStylusInfo.getId();
2226 auto toolTypeDevice =
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002227 AllOf(WithToolType(ToolType::STYLUS), WithDeviceId(touchscreenId));
Prabir Pradhan9a561c22022-11-07 16:11:23 +00002228
2229 // Press the stylus button.
2230 TestFixture::mStylus->pressKey(BTN_STYLUS);
2231 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2232 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2233 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2234
2235 // Start hovering with the stylus.
2236 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2237 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2238 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2239 TestFixture::mTouchscreen->sendMove(centerPoint);
2240 TestFixture::mTouchscreen->sendSync();
2241 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2242 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2243 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2244 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2245 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2246 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2247 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2248 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
2249 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2250
2251 // Touch down with the stylus.
2252 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2253 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2254 TestFixture::mTouchscreen->sendDown(centerPoint);
2255 TestFixture::mTouchscreen->sendSync();
2256 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2257 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
2258 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2259
2260 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2261 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
2262 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2263
2264 // Stop touching with the stylus, and start hovering.
2265 TestFixture::mTouchscreen->sendUp();
2266 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2267 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2268 TestFixture::mTouchscreen->sendMove(centerPoint);
2269 TestFixture::mTouchscreen->sendSync();
2270 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2271 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_UP),
2272 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2273 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2274 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2275 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2276 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2277 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2278 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2279
2280 // Stop hovering.
2281 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2282 TestFixture::mTouchscreen->sendSync();
2283 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2284 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
2285 WithButtonState(0))));
2286 // TODO(b/257971675): Fix inconsistent button state when exiting hover.
2287 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2288 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
2289 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2290
2291 // Release the stylus button.
2292 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2293 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2294 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
2295 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2296}
2297
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002298TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsWithinTouchGesture) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002299 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2300 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2301 const auto stylusId = TestFixture::mStylusInfo.getId();
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002302
2303 // Start a stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002304 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2305 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2306 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2307 TestFixture::mTouchscreen->sendDown(centerPoint);
2308 TestFixture::mTouchscreen->sendSync();
2309 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002310 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002311 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002312 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002313
2314 // Press and release a stylus button. Each change in button state also generates a MOVE event.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002315 TestFixture::mStylus->pressKey(BTN_STYLUS);
2316 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002317 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002318 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2319 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002320 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002321 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002322 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2323 WithDeviceId(touchscreenId))));
2324 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002325 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
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))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002329
Prabir Pradhan124ea442022-10-28 20:27:44 +00002330 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2331 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002332 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002333 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2334 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002335 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002336 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002337 WithDeviceId(touchscreenId))));
2338 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002339 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002340 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002341 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002342
2343 // Finish the stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002344 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2345 TestFixture::mTouchscreen->sendSync();
2346 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002347 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002348 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002349 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002350}
2351
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002352TYPED_TEST(StylusButtonIntegrationTest, StylusButtonMotionEventsDisabled) {
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002353 TestFixture::mFakePolicy->setStylusButtonMotionEventsEnabled(false);
2354 TestFixture::mReader->requestRefreshConfiguration(
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002355 InputReaderConfiguration::Change::STYLUS_BUTTON_REPORTING);
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002356
2357 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2358 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2359 const auto stylusId = TestFixture::mStylusInfo.getId();
2360
2361 // Start a stylus gesture. By the time this event is processed, the configuration change that
2362 // was requested is guaranteed to be completed.
2363 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2364 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2365 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2366 TestFixture::mTouchscreen->sendDown(centerPoint);
2367 TestFixture::mTouchscreen->sendSync();
2368 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2369 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002370 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002371 WithDeviceId(touchscreenId))));
2372
2373 // Press and release a stylus button. Each change only generates a MOVE motion event.
2374 // Key events are unaffected.
2375 TestFixture::mStylus->pressKey(BTN_STYLUS);
2376 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2377 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2378 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2379 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2380 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002381 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002382 WithDeviceId(touchscreenId))));
2383
2384 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2385 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2386 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
2387 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2388 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2389 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002390 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002391 WithDeviceId(touchscreenId))));
2392
2393 // Finish the stylus gesture.
2394 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2395 TestFixture::mTouchscreen->sendSync();
2396 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2397 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002398 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002399 WithDeviceId(touchscreenId))));
2400}
2401
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002402// --- ExternalStylusIntegrationTest ---
2403
2404// Verify the behavior of an external stylus. An external stylus can report pressure or button
2405// data independently of the touchscreen, which is then sent as a MotionEvent as part of an
2406// ongoing stylus gesture that is being emitted by the touchscreen.
Arpit Singh440bf652023-08-09 09:23:43 +00002407using ExternalStylusIntegrationTest = BaseTouchIntegrationTest;
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002408
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002409TEST_F(ExternalStylusIntegrationTest, ExternalStylusConnectionChangesTouchscreenSource) {
2410 // Create an external stylus capable of reporting pressure data that
2411 // should be fused with a touch pointer.
2412 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2413 createUinputDevice<UinputExternalStylusWithPressure>();
2414 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
2415 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002416 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002417 ASSERT_TRUE(stylusInfo);
2418
2419 // Connecting an external stylus changes the source of the touchscreen.
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002420 const auto deviceInfo = waitForDevice(mDevice->getName());
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002421 ASSERT_TRUE(deviceInfo);
2422 ASSERT_TRUE(isFromSource(deviceInfo->getSources(), STYLUS_FUSION_SOURCE));
2423}
2424
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002425TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureReported) {
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002426 const Point centerPoint = mDevice->getCenterPoint();
2427
2428 // Create an external stylus capable of reporting pressure data that
2429 // should be fused with a touch pointer.
2430 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2431 createUinputDevice<UinputExternalStylusWithPressure>();
2432 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
2433 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002434 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002435 ASSERT_TRUE(stylusInfo);
2436
2437 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2438
2439 const auto touchscreenId = mDeviceInfo.getId();
2440
2441 // Set a pressure value on the stylus. It doesn't generate any events.
2442 const auto& RAW_PRESSURE_MAX = UinputExternalStylusWithPressure::RAW_PRESSURE_MAX;
2443 stylus->setPressure(100);
2444 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2445
2446 // Start a finger gesture, and ensure it shows up as stylus gesture
2447 // with the pressure set by the external stylus.
Dominik Laskowski2f01d772022-03-23 16:01:29 -07002448 mDevice->sendSlot(FIRST_SLOT);
Chris Ye1b0c7342020-07-28 21:57:03 -07002449 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002450 mDevice->sendToolType(MT_TOOL_FINGER);
Prabir Pradhanb54ffb22022-10-27 18:03:34 +00002451 mDevice->sendDown(centerPoint);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002452 mDevice->sendSync();
2453 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002454 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithToolType(ToolType::STYLUS),
2455 WithButtonState(0), WithSource(STYLUS_FUSION_SOURCE), WithDeviceId(touchscreenId),
2456 WithPressure(100.f / RAW_PRESSURE_MAX))));
Dominik Laskowski2f01d772022-03-23 16:01:29 -07002457
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002458 // Change the pressure on the external stylus, and ensure the touchscreen generates a MOVE
2459 // event with the updated pressure.
2460 stylus->setPressure(200);
Vaibhav Devmuraridd82b8e2022-08-16 15:34:01 +00002461 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002462 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithToolType(ToolType::STYLUS),
2463 WithButtonState(0), WithSource(STYLUS_FUSION_SOURCE), WithDeviceId(touchscreenId),
2464 WithPressure(200.f / RAW_PRESSURE_MAX))));
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002465
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002466 // The external stylus did not generate any events.
2467 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2468 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
2469}
2470
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002471TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureNotReported) {
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002472 const Point centerPoint = mDevice->getCenterPoint();
2473
2474 // Create an external stylus capable of reporting pressure data that
2475 // should be fused with a touch pointer.
2476 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2477 createUinputDevice<UinputExternalStylusWithPressure>();
2478 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
2479 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002480 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002481 ASSERT_TRUE(stylusInfo);
2482
2483 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2484
2485 const auto touchscreenId = mDeviceInfo.getId();
2486
2487 // Set a pressure value of 0 on the stylus. It doesn't generate any events.
2488 const auto& RAW_PRESSURE_MAX = UinputExternalStylusWithPressure::RAW_PRESSURE_MAX;
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002489 // Send a non-zero value first to prevent the kernel from consuming the zero event.
2490 stylus->setPressure(100);
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002491 stylus->setPressure(0);
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002492 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002493
2494 // Start a finger gesture. The touch device will withhold generating any touches for
2495 // up to 72 milliseconds while waiting for pressure data from the external stylus.
2496 mDevice->sendSlot(FIRST_SLOT);
2497 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2498 mDevice->sendToolType(MT_TOOL_FINGER);
2499 mDevice->sendDown(centerPoint);
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002500 const auto syncTime = std::chrono::system_clock::now();
2501 // After 72 ms, the event *will* be generated. If we wait the full 72 ms to check that NO event
2502 // is generated in that period, there will be a race condition between the event being generated
2503 // and the test's wait timeout expiring. Thus, we wait for a shorter duration in the test, which
2504 // will reduce the liklihood of the race condition occurring.
2505 const auto waitUntilTimeForNoEvent =
2506 syncTime + std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT / 2));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07002507 mDevice->sendSync();
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002508 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled(waitUntilTimeForNoEvent));
Michael Wrightd02c5b62014-02-10 15:10:22 -08002509
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002510 // Since the external stylus did not report a pressure value within the timeout,
2511 // it shows up as a finger pointer.
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002512 const auto waitUntilTimeForEvent = syncTime +
2513 std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT)) + EVENT_HAPPENED_TIMEOUT;
2514 ASSERT_NO_FATAL_FAILURE(
2515 mTestListener->assertNotifyMotionWasCalled(AllOf(WithMotionAction(
2516 AMOTION_EVENT_ACTION_DOWN),
2517 WithSource(AINPUT_SOURCE_TOUCHSCREEN |
2518 AINPUT_SOURCE_STYLUS),
2519 WithToolType(ToolType::FINGER),
2520 WithDeviceId(touchscreenId),
2521 WithPressure(1.f)),
2522 waitUntilTimeForEvent));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002523
2524 // Change the pressure on the external stylus. Since the pressure was not present at the start
2525 // of the gesture, it is ignored for now.
2526 stylus->setPressure(200);
2527 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2528
2529 // Finish the finger gesture.
Michael Wrightd02c5b62014-02-10 15:10:22 -08002530 mDevice->sendTrackingId(INVALID_TRACKING_ID);
2531 mDevice->sendSync();
2532 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2533 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002534 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002535 WithToolType(ToolType::FINGER))));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002536
2537 // Start a new gesture. Since we have a valid pressure value, it shows up as a stylus.
2538 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2539 mDevice->sendToolType(MT_TOOL_FINGER);
2540 mDevice->sendDown(centerPoint);
2541 mDevice->sendSync();
2542 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002543 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithSource(STYLUS_FUSION_SOURCE),
2544 WithToolType(ToolType::STYLUS), WithButtonState(0), WithDeviceId(touchscreenId),
2545 WithPressure(200.f / RAW_PRESSURE_MAX))));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002546
2547 // The external stylus did not generate any events.
2548 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2549 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002550}
Siarhei Vishniakou1983a712021-06-04 19:27:09 +00002551
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002552TEST_F(ExternalStylusIntegrationTest, UnfusedExternalStylus) {
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002553 const Point centerPoint = mDevice->getCenterPoint();
2554
2555 // Create an external stylus device that does not support pressure. It should not affect any
2556 // touch pointers.
2557 std::unique_ptr<UinputExternalStylus> stylus = createUinputDevice<UinputExternalStylus>();
2558 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
2559 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002560 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002561 ASSERT_TRUE(stylusInfo);
2562
2563 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2564
2565 const auto touchscreenId = mDeviceInfo.getId();
2566
2567 // Start a finger gesture and ensure a finger pointer is generated for it, without waiting for
2568 // pressure data from the external stylus.
2569 mDevice->sendSlot(FIRST_SLOT);
2570 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2571 mDevice->sendToolType(MT_TOOL_FINGER);
2572 mDevice->sendDown(centerPoint);
2573 auto waitUntil = std::chrono::system_clock::now() +
2574 std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT));
2575 mDevice->sendSync();
2576 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002577 mTestListener->assertNotifyMotionWasCalled(AllOf(WithMotionAction(
2578 AMOTION_EVENT_ACTION_DOWN),
2579 WithToolType(ToolType::FINGER),
2580 WithSource(AINPUT_SOURCE_TOUCHSCREEN |
2581 AINPUT_SOURCE_STYLUS),
2582 WithButtonState(0),
2583 WithDeviceId(touchscreenId),
2584 WithPressure(1.f)),
2585 waitUntil));
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002586
2587 // The external stylus did not generate any events.
2588 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2589 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
2590}
2591
Michael Wrightd02c5b62014-02-10 15:10:22 -08002592// --- InputDeviceTest ---
2593class InputDeviceTest : public testing::Test {
2594protected:
2595 static const char* DEVICE_NAME;
2596 static const char* DEVICE_LOCATION;
2597 static const int32_t DEVICE_ID;
2598 static const int32_t DEVICE_GENERATION;
2599 static const int32_t DEVICE_CONTROLLER_NUMBER;
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002600 static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002601 static const int32_t EVENTHUB_ID;
2602 static const std::string DEVICE_BLUETOOTH_ADDRESS;
2603
2604 std::shared_ptr<FakeEventHub> mFakeEventHub;
2605 sp<FakeInputReaderPolicy> mFakePolicy;
2606 std::unique_ptr<TestInputListener> mFakeListener;
2607 std::unique_ptr<InstrumentedInputReader> mReader;
2608 std::shared_ptr<InputDevice> mDevice;
2609
2610 void SetUp() override {
2611 mFakeEventHub = std::make_unique<FakeEventHub>();
2612 mFakePolicy = sp<FakeInputReaderPolicy>::make();
2613 mFakeListener = std::make_unique<TestInputListener>();
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002614 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Michael Wrightd02c5b62014-02-10 15:10:22 -08002615 *mFakeListener);
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002616 InputDeviceIdentifier identifier;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002617 identifier.name = DEVICE_NAME;
2618 identifier.location = DEVICE_LOCATION;
2619 identifier.bluetoothAddress = DEVICE_BLUETOOTH_ADDRESS;
2620 mDevice = std::make_shared<InputDevice>(mReader->getContext(), DEVICE_ID, DEVICE_GENERATION,
2621 identifier);
2622 mReader->pushNextDevice(mDevice);
2623 mFakeEventHub->addDevice(EVENTHUB_ID, DEVICE_NAME, ftl::Flags<InputDeviceClass>(0));
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002624 mReader->loopOnce();
Michael Wrightd02c5b62014-02-10 15:10:22 -08002625 }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002626
2627 void TearDown() override {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002628 mFakeListener.reset();
2629 mFakePolicy.clear();
2630 }
2631};
2632
2633const char* InputDeviceTest::DEVICE_NAME = "device";
2634const char* InputDeviceTest::DEVICE_LOCATION = "USB1";
2635const int32_t InputDeviceTest::DEVICE_ID = END_RESERVED_ID + 1000;
2636const int32_t InputDeviceTest::DEVICE_GENERATION = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002637const int32_t InputDeviceTest::DEVICE_CONTROLLER_NUMBER = 0;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002638const ftl::Flags<InputDeviceClass> InputDeviceTest::DEVICE_CLASSES =
2639 InputDeviceClass::KEYBOARD | InputDeviceClass::TOUCH | InputDeviceClass::JOYSTICK;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002640const int32_t InputDeviceTest::EVENTHUB_ID = 1;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002641const std::string InputDeviceTest::DEVICE_BLUETOOTH_ADDRESS = "11:AA:22:BB:33:CC";
2642
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002643TEST_F(InputDeviceTest, ImmutableProperties) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002644 ASSERT_EQ(DEVICE_ID, mDevice->getId());
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002645 ASSERT_STREQ(DEVICE_NAME, mDevice->getName().c_str());
2646 ASSERT_EQ(ftl::Flags<InputDeviceClass>(0), mDevice->getClasses());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002647}
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002648
Michael Wrightd02c5b62014-02-10 15:10:22 -08002649TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsFalse) {
2650 ASSERT_EQ(mDevice->isEnabled(), false);
2651}
2652
2653TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
2654 // Configuration.
2655 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002656 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002657
2658 // Reset.
2659 unused += mDevice->reset(ARBITRARY_TIME);
2660
2661 NotifyDeviceResetArgs resetArgs;
2662 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
2663 ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
2664 ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
2665
2666 // Metadata.
2667 ASSERT_TRUE(mDevice->isIgnored());
2668 ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mDevice->getSources());
2669
2670 InputDeviceInfo info = mDevice->getDeviceInfo();
2671 ASSERT_EQ(DEVICE_ID, info.getId());
2672 ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.c_str());
2673 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NONE, info.getKeyboardType());
2674 ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, info.getSources());
2675
2676 // State queries.
2677 ASSERT_EQ(0, mDevice->getMetaState());
2678
2679 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, 0))
2680 << "Ignored device should return unknown key code state.";
2681 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 0))
2682 << "Ignored device should return unknown scan code state.";
2683 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 0))
2684 << "Ignored device should return unknown switch state.";
2685
2686 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B};
2687 uint8_t flags[2] = { 0, 1 };
2688 ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, keyCodes, flags))
2689 << "Ignored device should never mark any key codes.";
2690 ASSERT_EQ(0, flags[0]) << "Flag for unsupported key should be unchanged.";
2691 ASSERT_EQ(1, flags[1]) << "Flag for unsupported key should be unchanged.";
2692}
2693
2694TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRequestsToMappers) {
2695 // Configuration.
2696 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "key", "value");
2697
2698 FakeInputMapper& mapper1 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00002699 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2700 AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002701 mapper1.setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC);
2702 mapper1.setMetaState(AMETA_ALT_ON);
2703 mapper1.addSupportedKeyCode(AKEYCODE_A);
2704 mapper1.addSupportedKeyCode(AKEYCODE_B);
2705 mapper1.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
2706 mapper1.setKeyCodeState(AKEYCODE_B, AKEY_STATE_UP);
2707 mapper1.setScanCodeState(2, AKEY_STATE_DOWN);
2708 mapper1.setScanCodeState(3, AKEY_STATE_UP);
2709 mapper1.setSwitchState(4, AKEY_STATE_DOWN);
2710
2711 FakeInputMapper& mapper2 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00002712 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2713 AINPUT_SOURCE_TOUCHSCREEN);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002714 mapper2.setMetaState(AMETA_SHIFT_ON);
2715
2716 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002717 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002718
Harry Cuttsf13161a2023-03-08 14:15:49 +00002719 std::optional<std::string> propertyValue = mDevice->getConfiguration().getString("key");
2720 ASSERT_TRUE(propertyValue.has_value())
Michael Wrightd02c5b62014-02-10 15:10:22 -08002721 << "Device should have read configuration during configuration phase.";
Harry Cuttsf13161a2023-03-08 14:15:49 +00002722 ASSERT_EQ("value", *propertyValue);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002723
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002724 ASSERT_NO_FATAL_FAILURE(mapper1.assertConfigureWasCalled());
2725 ASSERT_NO_FATAL_FAILURE(mapper2.assertConfigureWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002726
2727 // Reset
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002728 unused += mDevice->reset(ARBITRARY_TIME);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002729 ASSERT_NO_FATAL_FAILURE(mapper1.assertResetWasCalled());
2730 ASSERT_NO_FATAL_FAILURE(mapper2.assertResetWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002731
2732 NotifyDeviceResetArgs resetArgs;
2733 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
2734 ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
2735 ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
2736
2737 // Metadata.
2738 ASSERT_FALSE(mDevice->isIgnored());
2739 ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), mDevice->getSources());
2740
Siarhei Vishniakou1983a712021-06-04 19:27:09 +00002741 InputDeviceInfo info = mDevice->getDeviceInfo();
Michael Wrightd02c5b62014-02-10 15:10:22 -08002742 ASSERT_EQ(DEVICE_ID, info.getId());
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002743 ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002744 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, info.getKeyboardType());
2745 ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), info.getSources());
2746
2747 // State queries.
2748 ASSERT_EQ(AMETA_ALT_ON | AMETA_SHIFT_ON, mDevice->getMetaState())
2749 << "Should query mappers and combine meta states.";
2750
2751 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2752 << "Should return unknown key code state when source not supported.";
2753 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2754 << "Should return unknown scan code state when source not supported.";
2755 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2756 << "Should return unknown switch state when source not supported.";
2757
2758 ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, AKEYCODE_A))
2759 << "Should query mapper when source is supported.";
2760 ASSERT_EQ(AKEY_STATE_UP, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 3))
2761 << "Should query mapper when source is supported.";
2762 ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 4))
2763 << "Should query mapper when source is supported.";
2764
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002765 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2};
Michael Wrightd02c5b62014-02-10 15:10:22 -08002766 uint8_t flags[4] = { 0, 0, 0, 1 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002767 ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -08002768 << "Should do nothing when source is unsupported.";
2769 ASSERT_EQ(0, flags[0]) << "Flag should be unchanged when source is unsupported.";
2770 ASSERT_EQ(0, flags[1]) << "Flag should be unchanged when source is unsupported.";
2771 ASSERT_EQ(0, flags[2]) << "Flag should be unchanged when source is unsupported.";
2772 ASSERT_EQ(1, flags[3]) << "Flag should be unchanged when source is unsupported.";
2773
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002774 ASSERT_TRUE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -08002775 << "Should query mapper when source is supported.";
2776 ASSERT_EQ(1, flags[0]) << "Flag for supported key should be set.";
2777 ASSERT_EQ(1, flags[1]) << "Flag for supported key should be set.";
2778 ASSERT_EQ(0, flags[2]) << "Flag for unsupported key should be unchanged.";
2779 ASSERT_EQ(1, flags[3]) << "Flag for unsupported key should be unchanged.";
2780
2781 // Event handling.
2782 RawEvent event;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002783 event.deviceId = EVENTHUB_ID;
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002784 unused += mDevice->process(&event, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002785
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002786 ASSERT_NO_FATAL_FAILURE(mapper1.assertProcessWasCalled());
2787 ASSERT_NO_FATAL_FAILURE(mapper2.assertProcessWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002788}
2789
Yeabkal Wubshitb1b96db2024-01-24 12:47:00 -08002790TEST_F(InputDeviceTest, Configure_SmoothScrollViewBehaviorNotSet) {
2791 // Set some behavior to force the configuration to be update.
2792 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "1");
2793 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2794 AINPUT_SOURCE_KEYBOARD);
2795
2796 std::list<NotifyArgs> unused =
2797 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2798 /*changes=*/{});
2799
2800 ASSERT_FALSE(mDevice->getDeviceInfo().getViewBehavior().shouldSmoothScroll.has_value());
2801}
2802
2803TEST_F(InputDeviceTest, Configure_SmoothScrollViewBehaviorEnabled) {
2804 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.viewBehavior_smoothScroll", "1");
2805 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2806 AINPUT_SOURCE_KEYBOARD);
2807
2808 std::list<NotifyArgs> unused =
2809 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2810 /*changes=*/{});
2811
2812 ASSERT_TRUE(mDevice->getDeviceInfo().getViewBehavior().shouldSmoothScroll.value_or(false));
2813}
2814
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -07002815TEST_F(InputDeviceTest, WakeDevice_AddsWakeFlagToProcessNotifyArgs) {
2816 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "1");
2817 FakeInputMapper& mapper =
2818 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2819 AINPUT_SOURCE_KEYBOARD);
2820 NotifyMotionArgs args1;
2821 NotifySwitchArgs args2;
2822 NotifyKeyArgs args3;
2823 mapper.setProcessResult({args1, args2, args3});
2824
2825 InputReaderConfiguration config;
2826 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2827
2828 RawEvent event;
2829 event.deviceId = EVENTHUB_ID;
2830 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2831
2832 for (auto& arg : notifyArgs) {
2833 if (const auto notifyMotionArgs = std::get_if<NotifyMotionArgs>(&arg)) {
2834 ASSERT_EQ(POLICY_FLAG_WAKE, notifyMotionArgs->policyFlags);
2835 } else if (const auto notifySwitchArgs = std::get_if<NotifySwitchArgs>(&arg)) {
2836 ASSERT_EQ(POLICY_FLAG_WAKE, notifySwitchArgs->policyFlags);
2837 } else if (const auto notifyKeyArgs = std::get_if<NotifyKeyArgs>(&arg)) {
2838 ASSERT_EQ(POLICY_FLAG_WAKE, notifyKeyArgs->policyFlags);
2839 }
2840 }
2841}
2842
2843TEST_F(InputDeviceTest, NotWakeDevice_DoesNotAddWakeFlagToProcessNotifyArgs) {
2844 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "0");
2845 FakeInputMapper& mapper =
2846 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2847 AINPUT_SOURCE_KEYBOARD);
2848 NotifyMotionArgs args;
2849 mapper.setProcessResult({args});
2850
2851 InputReaderConfiguration config;
2852 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2853
2854 RawEvent event;
2855 event.deviceId = EVENTHUB_ID;
2856 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2857
2858 // POLICY_FLAG_WAKE is not added to the NotifyArgs.
2859 ASSERT_EQ(0u, std::get<NotifyMotionArgs>(notifyArgs.front()).policyFlags);
2860}
2861
2862TEST_F(InputDeviceTest, NotWakeDevice_DoesNotRemoveExistingWakeFlagFromProcessNotifyArgs) {
2863 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "0");
2864 FakeInputMapper& mapper =
2865 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2866 AINPUT_SOURCE_KEYBOARD);
2867 NotifyMotionArgs args;
2868 args.policyFlags = POLICY_FLAG_WAKE;
2869 mapper.setProcessResult({args});
2870
2871 InputReaderConfiguration config;
2872 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2873
2874 RawEvent event;
2875 event.deviceId = EVENTHUB_ID;
2876 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2877
2878 // The POLICY_FLAG_WAKE is preserved, despite the device being a non-wake device.
2879 ASSERT_EQ(POLICY_FLAG_WAKE, std::get<NotifyMotionArgs>(notifyArgs.front()).policyFlags);
2880}
2881
Arthur Hung2c9a3342019-07-23 14:18:59 +08002882// A single input device is associated with a specific display. Check that:
2883// 1. Device is disabled if the viewport corresponding to the associated display is not found
Arpit Singh48189772023-05-30 14:12:49 +00002884// 2. Device is disabled when configure API is called
Arthur Hung2c9a3342019-07-23 14:18:59 +08002885TEST_F(InputDeviceTest, Configure_AssignsDisplayPort) {
Arpit Singh8e6fb252023-04-06 11:49:17 +00002886 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2887 AINPUT_SOURCE_TOUCHSCREEN);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002888
2889 // First Configuration.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002890 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002891 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2892 /*changes=*/{});
Arthur Hung2c9a3342019-07-23 14:18:59 +08002893
2894 // Device should be enabled by default.
2895 ASSERT_TRUE(mDevice->isEnabled());
2896
2897 // Prepare associated info.
2898 constexpr uint8_t hdmi = 1;
2899 const std::string UNIQUE_ID = "local:1";
2900
2901 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002902 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002903 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002904 // Device should be disabled because it is associated with a specific display via
2905 // input port <-> display port association, but the corresponding display is not found
2906 ASSERT_FALSE(mDevice->isEnabled());
2907
2908 // Prepare displays.
2909 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +00002910 ui::ROTATION_0, /*isActive=*/true, UNIQUE_ID, hdmi,
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00002911 ViewportType::INTERNAL);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002912 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002913 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002914 ASSERT_TRUE(mDevice->isEnabled());
2915
2916 // Device should be disabled after set disable.
2917 mFakePolicy->addDisabledDevice(mDevice->getId());
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002918 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002919 InputReaderConfiguration::Change::ENABLED_STATE);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002920 ASSERT_FALSE(mDevice->isEnabled());
2921
2922 // Device should still be disabled even found the associated display.
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::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002925 ASSERT_FALSE(mDevice->isEnabled());
2926}
Michael Wrightd02c5b62014-02-10 15:10:22 -08002927
Christine Franks1ba71cc2021-04-07 14:37:42 -07002928TEST_F(InputDeviceTest, Configure_AssignsDisplayUniqueId) {
2929 // Device should be enabled by default.
2930 mFakePolicy->clearViewports();
Arpit Singh8e6fb252023-04-06 11:49:17 +00002931 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2932 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002933 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002934 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2935 /*changes=*/{});
Christine Franks1ba71cc2021-04-07 14:37:42 -07002936 ASSERT_TRUE(mDevice->isEnabled());
2937
2938 // Device should be disabled because it is associated with a specific display, but the
2939 // corresponding display is not found.
Christine Franks2a2293c2022-01-18 11:51:16 -08002940 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002941 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002942 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002943 ASSERT_FALSE(mDevice->isEnabled());
2944
2945 // Device should be enabled when a display is found.
2946 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00002947 ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
Christine Franks1ba71cc2021-04-07 14:37:42 -07002948 NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002949 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002950 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002951 ASSERT_TRUE(mDevice->isEnabled());
2952
2953 // Device should be disabled after set disable.
2954 mFakePolicy->addDisabledDevice(mDevice->getId());
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002955 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002956 InputReaderConfiguration::Change::ENABLED_STATE);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002957 ASSERT_FALSE(mDevice->isEnabled());
2958
2959 // Device should still be disabled even found the associated display.
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::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002962 ASSERT_FALSE(mDevice->isEnabled());
2963}
2964
Christine Franks2a2293c2022-01-18 11:51:16 -08002965TEST_F(InputDeviceTest, Configure_UniqueId_CorrectlyMatches) {
2966 mFakePolicy->clearViewports();
Arpit Singh8e6fb252023-04-06 11:49:17 +00002967 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2968 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002969 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002970 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2971 /*changes=*/{});
Christine Franks2a2293c2022-01-18 11:51:16 -08002972
Christine Franks2a2293c2022-01-18 11:51:16 -08002973 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
2974 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00002975 ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
Christine Franks2a2293c2022-01-18 11:51:16 -08002976 NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan55c5ee22024-02-14 06:03:02 +00002977 const auto initialGeneration = mDevice->getGeneration();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002978 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002979 InputReaderConfiguration::Change::DISPLAY_INFO);
Antonio Kantek0ac5e092024-04-22 17:10:27 +00002980 ASSERT_EQ(DISPLAY_UNIQUE_ID, mDevice->getAssociatedDisplayUniqueIdByPort());
Prabir Pradhan55c5ee22024-02-14 06:03:02 +00002981 ASSERT_GT(mDevice->getGeneration(), initialGeneration);
2982 ASSERT_EQ(mDevice->getDeviceInfo().getAssociatedDisplayId(), SECONDARY_DISPLAY_ID);
Christine Franks2a2293c2022-01-18 11:51:16 -08002983}
2984
Siarhei Vishniakou30feb8c2022-09-28 10:48:29 -07002985/**
2986 * This test reproduces a crash caused by a dangling reference that remains after device is added
2987 * and removed. The reference is accessed in InputDevice::dump(..);
2988 */
2989TEST_F(InputDeviceTest, DumpDoesNotCrash) {
2990 constexpr int32_t TEST_EVENTHUB_ID = 10;
2991 mFakeEventHub->addDevice(TEST_EVENTHUB_ID, "Test EventHub device", InputDeviceClass::BATTERY);
2992
Harry Cutts33476232023-01-30 19:57:29 +00002993 InputDevice device(mReader->getContext(), /*id=*/1, /*generation=*/2, /*identifier=*/{});
Arpit Singh82f29a12023-06-13 15:05:53 +00002994 auto _ = device.addEventHubDevice(ARBITRARY_TIME, TEST_EVENTHUB_ID,
2995 mFakePolicy->getReaderConfiguration());
Siarhei Vishniakou30feb8c2022-09-28 10:48:29 -07002996 device.removeEventHubDevice(TEST_EVENTHUB_ID);
2997 std::string dumpStr, eventHubDevStr;
2998 device.dump(dumpStr, eventHubDevStr);
2999}
3000
Prabir Pradhanb54ffb22022-10-27 18:03:34 +00003001TEST_F(InputDeviceTest, GetBluetoothAddress) {
3002 const auto& address = mReader->getBluetoothAddress(DEVICE_ID);
3003 ASSERT_TRUE(address);
3004 ASSERT_EQ(DEVICE_BLUETOOTH_ADDRESS, *address);
3005}
3006
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003007TEST_F(InputDeviceTest, KernelBufferOverflowResetsMappers) {
3008 mFakePolicy->clearViewports();
3009 FakeInputMapper& mapper =
3010 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
3011 AINPUT_SOURCE_KEYBOARD);
3012 std::list<NotifyArgs> unused =
3013 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
3014 /*changes=*/{});
3015
3016 mapper.assertConfigureWasCalled();
3017 mapper.assertResetWasNotCalled();
3018
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -08003019 RawEvent event{.when = ARBITRARY_TIME,
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003020 .readTime = ARBITRARY_TIME,
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -08003021 .deviceId = EVENTHUB_ID,
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003022 .type = EV_SYN,
3023 .code = SYN_REPORT,
3024 .value = 0};
3025
3026 // Events are processed normally.
3027 unused = mDevice->process(&event, /*count=*/1);
3028 mapper.assertProcessWasCalled();
3029
3030 // Simulate a kernel buffer overflow, which generates a SYN_DROPPED event.
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003031 event.type = EV_SYN;
3032 event.code = SYN_DROPPED;
3033 event.value = 0;
3034 unused = mDevice->process(&event, /*count=*/1);
3035 mapper.assertProcessWasNotCalled();
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003036
3037 // All events until the next SYN_REPORT should be dropped.
3038 event.type = EV_KEY;
3039 event.code = KEY_A;
3040 event.value = 1;
3041 unused = mDevice->process(&event, /*count=*/1);
3042 mapper.assertProcessWasNotCalled();
3043
3044 // We get the SYN_REPORT event now, which is not forwarded to mappers.
Arpit Singh4b4a4572023-11-24 18:19:56 +00003045 // This should reset the mapper.
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003046 event.type = EV_SYN;
3047 event.code = SYN_REPORT;
3048 event.value = 0;
3049 unused = mDevice->process(&event, /*count=*/1);
3050 mapper.assertProcessWasNotCalled();
Arpit Singh4b4a4572023-11-24 18:19:56 +00003051 mapper.assertResetWasCalled();
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003052
3053 // The mapper receives events normally now.
3054 event.type = EV_KEY;
3055 event.code = KEY_B;
3056 event.value = 1;
3057 unused = mDevice->process(&event, /*count=*/1);
3058 mapper.assertProcessWasCalled();
3059}
3060
Michael Wrightd02c5b62014-02-10 15:10:22 -08003061// --- SwitchInputMapperTest ---
3062
3063class SwitchInputMapperTest : public InputMapperTest {
3064protected:
3065};
3066
3067TEST_F(SwitchInputMapperTest, GetSources) {
Arpit Singhdf992eb2023-04-26 16:12:10 +00003068 SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08003069
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003070 ASSERT_EQ(uint32_t(AINPUT_SOURCE_SWITCH), mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003071}
3072
3073TEST_F(SwitchInputMapperTest, GetSwitchState) {
Arpit Singhdf992eb2023-04-26 16:12:10 +00003074 SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08003075
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003076 mFakeEventHub->setSwitchState(EVENTHUB_ID, SW_LID, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003077 ASSERT_EQ(1, mapper.getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003078
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003079 mFakeEventHub->setSwitchState(EVENTHUB_ID, SW_LID, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003080 ASSERT_EQ(0, mapper.getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003081}
3082
3083TEST_F(SwitchInputMapperTest, Process) {
Arpit Singhdf992eb2023-04-26 16:12:10 +00003084 SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003085 std::list<NotifyArgs> out;
3086 out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SW, SW_LID, 1);
3087 ASSERT_TRUE(out.empty());
3088 out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SW, SW_JACK_PHYSICAL_INSERT, 1);
3089 ASSERT_TRUE(out.empty());
3090 out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SW, SW_HEADPHONE_INSERT, 0);
3091 ASSERT_TRUE(out.empty());
3092 out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003093
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003094 ASSERT_EQ(1u, out.size());
3095 const NotifySwitchArgs& args = std::get<NotifySwitchArgs>(*out.begin());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003096 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
Dan Albert1bd2fc02016-02-02 15:11:57 -08003097 ASSERT_EQ((1U << SW_LID) | (1U << SW_JACK_PHYSICAL_INSERT), args.switchValues);
3098 ASSERT_EQ((1U << SW_LID) | (1U << SW_JACK_PHYSICAL_INSERT) | (1 << SW_HEADPHONE_INSERT),
Michael Wrightd02c5b62014-02-10 15:10:22 -08003099 args.switchMask);
3100 ASSERT_EQ(uint32_t(0), args.policyFlags);
3101}
3102
Chris Ye87143712020-11-10 05:05:58 +00003103// --- VibratorInputMapperTest ---
3104class VibratorInputMapperTest : public InputMapperTest {
3105protected:
3106 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::VIBRATOR); }
3107};
3108
3109TEST_F(VibratorInputMapperTest, GetSources) {
Arpit Singh0f26b302023-04-26 16:23:13 +00003110 VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
Chris Ye87143712020-11-10 05:05:58 +00003111
3112 ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mapper.getSources());
3113}
3114
3115TEST_F(VibratorInputMapperTest, GetVibratorIds) {
Arpit Singh0f26b302023-04-26 16:23:13 +00003116 VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
Chris Ye87143712020-11-10 05:05:58 +00003117
3118 ASSERT_EQ(mapper.getVibratorIds().size(), 2U);
3119}
3120
3121TEST_F(VibratorInputMapperTest, Vibrate) {
3122 constexpr uint8_t DEFAULT_AMPLITUDE = 192;
Chris Yefb552902021-02-03 17:18:37 -08003123 constexpr int32_t VIBRATION_TOKEN = 100;
Arpit Singh0f26b302023-04-26 16:23:13 +00003124 VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
Chris Ye87143712020-11-10 05:05:58 +00003125
3126 VibrationElement pattern(2);
3127 VibrationSequence sequence(2);
3128 pattern.duration = std::chrono::milliseconds(200);
Harry Cutts33476232023-01-30 19:57:29 +00003129 pattern.channels = {{/*vibratorId=*/0, DEFAULT_AMPLITUDE / 2},
3130 {/*vibratorId=*/1, DEFAULT_AMPLITUDE}};
Chris Ye87143712020-11-10 05:05:58 +00003131 sequence.addElement(pattern);
3132 pattern.duration = std::chrono::milliseconds(500);
Harry Cutts33476232023-01-30 19:57:29 +00003133 pattern.channels = {{/*vibratorId=*/0, DEFAULT_AMPLITUDE / 4},
3134 {/*vibratorId=*/1, DEFAULT_AMPLITUDE}};
Chris Ye87143712020-11-10 05:05:58 +00003135 sequence.addElement(pattern);
3136
3137 std::vector<int64_t> timings = {0, 1};
3138 std::vector<uint8_t> amplitudes = {DEFAULT_AMPLITUDE, DEFAULT_AMPLITUDE / 2};
3139
3140 ASSERT_FALSE(mapper.isVibrating());
Chris Yefb552902021-02-03 17:18:37 -08003141 // Start vibrating
Harry Cutts33476232023-01-30 19:57:29 +00003142 std::list<NotifyArgs> out = mapper.vibrate(sequence, /*repeat=*/-1, VIBRATION_TOKEN);
Chris Ye87143712020-11-10 05:05:58 +00003143 ASSERT_TRUE(mapper.isVibrating());
Chris Yefb552902021-02-03 17:18:37 -08003144 // Verify vibrator state listener was notified.
3145 mReader->loopOnce();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003146 ASSERT_EQ(1u, out.size());
3147 const NotifyVibratorStateArgs& vibrateArgs = std::get<NotifyVibratorStateArgs>(*out.begin());
3148 ASSERT_EQ(DEVICE_ID, vibrateArgs.deviceId);
3149 ASSERT_TRUE(vibrateArgs.isOn);
Chris Yefb552902021-02-03 17:18:37 -08003150 // Stop vibrating
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003151 out = mapper.cancelVibrate(VIBRATION_TOKEN);
Chris Yefb552902021-02-03 17:18:37 -08003152 ASSERT_FALSE(mapper.isVibrating());
3153 // Verify vibrator state listener was notified.
3154 mReader->loopOnce();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003155 ASSERT_EQ(1u, out.size());
3156 const NotifyVibratorStateArgs& cancelArgs = std::get<NotifyVibratorStateArgs>(*out.begin());
3157 ASSERT_EQ(DEVICE_ID, cancelArgs.deviceId);
3158 ASSERT_FALSE(cancelArgs.isOn);
Chris Ye87143712020-11-10 05:05:58 +00003159}
Michael Wrightd02c5b62014-02-10 15:10:22 -08003160
Chris Yef59a2f42020-10-16 12:55:26 -07003161// --- SensorInputMapperTest ---
3162
3163class SensorInputMapperTest : public InputMapperTest {
3164protected:
3165 static const int32_t ACCEL_RAW_MIN;
3166 static const int32_t ACCEL_RAW_MAX;
3167 static const int32_t ACCEL_RAW_FUZZ;
3168 static const int32_t ACCEL_RAW_FLAT;
3169 static const int32_t ACCEL_RAW_RESOLUTION;
3170
3171 static const int32_t GYRO_RAW_MIN;
3172 static const int32_t GYRO_RAW_MAX;
3173 static const int32_t GYRO_RAW_FUZZ;
3174 static const int32_t GYRO_RAW_FLAT;
3175 static const int32_t GYRO_RAW_RESOLUTION;
3176
3177 static const float GRAVITY_MS2_UNIT;
3178 static const float DEGREE_RADIAN_UNIT;
3179
3180 void prepareAccelAxes();
3181 void prepareGyroAxes();
3182 void setAccelProperties();
3183 void setGyroProperties();
3184 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::SENSOR); }
3185};
3186
3187const int32_t SensorInputMapperTest::ACCEL_RAW_MIN = -32768;
3188const int32_t SensorInputMapperTest::ACCEL_RAW_MAX = 32768;
3189const int32_t SensorInputMapperTest::ACCEL_RAW_FUZZ = 16;
3190const int32_t SensorInputMapperTest::ACCEL_RAW_FLAT = 0;
3191const int32_t SensorInputMapperTest::ACCEL_RAW_RESOLUTION = 8192;
3192
3193const int32_t SensorInputMapperTest::GYRO_RAW_MIN = -2097152;
3194const int32_t SensorInputMapperTest::GYRO_RAW_MAX = 2097152;
3195const int32_t SensorInputMapperTest::GYRO_RAW_FUZZ = 16;
3196const int32_t SensorInputMapperTest::GYRO_RAW_FLAT = 0;
3197const int32_t SensorInputMapperTest::GYRO_RAW_RESOLUTION = 1024;
3198
3199const float SensorInputMapperTest::GRAVITY_MS2_UNIT = 9.80665f;
3200const float SensorInputMapperTest::DEGREE_RADIAN_UNIT = 0.0174533f;
3201
3202void SensorInputMapperTest::prepareAccelAxes() {
3203 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3204 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3205 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3206 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3207 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Z, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3208 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3209}
3210
3211void SensorInputMapperTest::prepareGyroAxes() {
3212 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RX, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3213 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3214 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RY, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3215 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3216 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RZ, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3217 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3218}
3219
3220void SensorInputMapperTest::setAccelProperties() {
3221 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 0, InputDeviceSensorType::ACCELEROMETER,
3222 /* sensorDataIndex */ 0);
3223 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 1, InputDeviceSensorType::ACCELEROMETER,
3224 /* sensorDataIndex */ 1);
3225 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 2, InputDeviceSensorType::ACCELEROMETER,
3226 /* sensorDataIndex */ 2);
3227 mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP);
3228 addConfigurationProperty("sensor.accelerometer.reportingMode", "0");
3229 addConfigurationProperty("sensor.accelerometer.maxDelay", "100000");
3230 addConfigurationProperty("sensor.accelerometer.minDelay", "5000");
3231 addConfigurationProperty("sensor.accelerometer.power", "1.5");
3232}
3233
3234void SensorInputMapperTest::setGyroProperties() {
3235 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 3, InputDeviceSensorType::GYROSCOPE,
3236 /* sensorDataIndex */ 0);
3237 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 4, InputDeviceSensorType::GYROSCOPE,
3238 /* sensorDataIndex */ 1);
3239 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 5, InputDeviceSensorType::GYROSCOPE,
3240 /* sensorDataIndex */ 2);
3241 mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP);
3242 addConfigurationProperty("sensor.gyroscope.reportingMode", "0");
3243 addConfigurationProperty("sensor.gyroscope.maxDelay", "100000");
3244 addConfigurationProperty("sensor.gyroscope.minDelay", "5000");
3245 addConfigurationProperty("sensor.gyroscope.power", "0.8");
3246}
3247
3248TEST_F(SensorInputMapperTest, GetSources) {
Arpit Singhfb706c32023-04-26 15:07:55 +00003249 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003250
3251 ASSERT_EQ(static_cast<uint32_t>(AINPUT_SOURCE_SENSOR), mapper.getSources());
3252}
3253
3254TEST_F(SensorInputMapperTest, ProcessAccelerometerSensor) {
3255 setAccelProperties();
3256 prepareAccelAxes();
Arpit Singhfb706c32023-04-26 15:07:55 +00003257 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003258
3259 ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::ACCELEROMETER,
3260 std::chrono::microseconds(10000),
3261 std::chrono::microseconds(0)));
Chris Yee14523a2020-12-19 13:46:00 -08003262 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003263 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, 20000);
3264 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, -20000);
3265 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Z, 40000);
3266 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000);
3267 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Chris Yef59a2f42020-10-16 12:55:26 -07003268
3269 NotifySensorArgs args;
3270 std::vector<float> values = {20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT,
3271 -20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT,
3272 40000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT};
3273
3274 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args));
3275 ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR);
3276 ASSERT_EQ(args.deviceId, DEVICE_ID);
3277 ASSERT_EQ(args.sensorType, InputDeviceSensorType::ACCELEROMETER);
3278 ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH);
3279 ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME);
3280 ASSERT_EQ(args.values, values);
3281 mapper.flushSensor(InputDeviceSensorType::ACCELEROMETER);
3282}
3283
3284TEST_F(SensorInputMapperTest, ProcessGyroscopeSensor) {
3285 setGyroProperties();
3286 prepareGyroAxes();
Arpit Singhfb706c32023-04-26 15:07:55 +00003287 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003288
3289 ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::GYROSCOPE,
3290 std::chrono::microseconds(10000),
3291 std::chrono::microseconds(0)));
Chris Yee14523a2020-12-19 13:46:00 -08003292 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003293 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RX, 20000);
3294 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RY, -20000);
3295 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RZ, 40000);
3296 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000);
3297 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Chris Yef59a2f42020-10-16 12:55:26 -07003298
3299 NotifySensorArgs args;
3300 std::vector<float> values = {20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT,
3301 -20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT,
3302 40000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT};
3303
3304 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args));
3305 ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR);
3306 ASSERT_EQ(args.deviceId, DEVICE_ID);
3307 ASSERT_EQ(args.sensorType, InputDeviceSensorType::GYROSCOPE);
3308 ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH);
3309 ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME);
3310 ASSERT_EQ(args.values, values);
3311 mapper.flushSensor(InputDeviceSensorType::GYROSCOPE);
3312}
3313
Michael Wrightd02c5b62014-02-10 15:10:22 -08003314// --- KeyboardInputMapperTest ---
3315
3316class KeyboardInputMapperTest : public InputMapperTest {
3317protected:
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003318 const std::string UNIQUE_ID = "local:0";
Zixuan Qufecb6062022-11-12 04:44:31 +00003319 const KeyboardLayoutInfo DEVICE_KEYBOARD_LAYOUT_INFO = KeyboardLayoutInfo("en-US", "qwerty");
Michael Wrighta9cf4192022-12-01 23:46:39 +00003320 void prepareDisplay(ui::Rotation orientation);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003321
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003322 void testDPadKeyRotation(KeyboardInputMapper& mapper, int32_t originalScanCode,
Arthur Hung2c9a3342019-07-23 14:18:59 +08003323 int32_t originalKeyCode, int32_t rotatedKeyCode,
Linnan Li13bf76a2024-05-05 19:18:02 +08003324 ui::LogicalDisplayId displayId = ui::ADISPLAY_ID_NONE);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003325};
3326
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003327/* Similar to setDisplayInfoAndReconfigure, but pre-populates all parameters except for the
3328 * orientation.
3329 */
Michael Wrighta9cf4192022-12-01 23:46:39 +00003330void KeyboardInputMapperTest::prepareDisplay(ui::Rotation orientation) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003331 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
3332 NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003333}
3334
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003335void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper& mapper,
Arthur Hung2c9a3342019-07-23 14:18:59 +08003336 int32_t originalScanCode, int32_t originalKeyCode,
Linnan Li13bf76a2024-05-05 19:18:02 +08003337 int32_t rotatedKeyCode,
3338 ui::LogicalDisplayId displayId) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003339 NotifyKeyArgs args;
3340
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003341 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003342 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3343 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3344 ASSERT_EQ(originalScanCode, args.scanCode);
3345 ASSERT_EQ(rotatedKeyCode, args.keyCode);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003346 ASSERT_EQ(displayId, args.displayId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003347
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003348 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003349 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3350 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3351 ASSERT_EQ(originalScanCode, args.scanCode);
3352 ASSERT_EQ(rotatedKeyCode, args.keyCode);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003353 ASSERT_EQ(displayId, args.displayId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003354}
3355
Michael Wrightd02c5b62014-02-10 15:10:22 -08003356TEST_F(KeyboardInputMapperTest, GetSources) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003357 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003358 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003359 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003360
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003361 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003362}
3363
3364TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) {
3365 const int32_t USAGE_A = 0x070004;
3366 const int32_t USAGE_UNKNOWN = 0x07ffff;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003367 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3368 mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
Chris Yea52ade12020-08-27 16:49:20 -07003369 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, POLICY_FLAG_WAKE);
3370 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, POLICY_FLAG_WAKE);
3371 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, POLICY_FLAG_WAKE);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003372
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003373 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003374 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003375 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Arthur Hung95f68612022-04-07 14:08:22 +08003376 // Initial metastate is AMETA_NONE.
3377 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003378
3379 // Key down by scan code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003380 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003381 NotifyKeyArgs args;
3382 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3383 ASSERT_EQ(DEVICE_ID, args.deviceId);
3384 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3385 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3386 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3387 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3388 ASSERT_EQ(KEY_HOME, args.scanCode);
3389 ASSERT_EQ(AMETA_NONE, args.metaState);
3390 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3391 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3392 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3393
3394 // Key up by scan code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003395 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003396 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3397 ASSERT_EQ(DEVICE_ID, args.deviceId);
3398 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3399 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3400 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3401 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3402 ASSERT_EQ(KEY_HOME, args.scanCode);
3403 ASSERT_EQ(AMETA_NONE, args.metaState);
3404 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3405 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3406 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3407
3408 // Key down by usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003409 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A);
3410 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, 0, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003411 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3412 ASSERT_EQ(DEVICE_ID, args.deviceId);
3413 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3414 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3415 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3416 ASSERT_EQ(AKEYCODE_A, args.keyCode);
3417 ASSERT_EQ(0, args.scanCode);
3418 ASSERT_EQ(AMETA_NONE, args.metaState);
3419 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3420 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3421 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3422
3423 // Key up by usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003424 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A);
3425 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003426 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3427 ASSERT_EQ(DEVICE_ID, args.deviceId);
3428 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3429 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3430 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3431 ASSERT_EQ(AKEYCODE_A, args.keyCode);
3432 ASSERT_EQ(0, args.scanCode);
3433 ASSERT_EQ(AMETA_NONE, args.metaState);
3434 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3435 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3436 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3437
3438 // Key down with unknown scan code or usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003439 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
3440 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003441 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3442 ASSERT_EQ(DEVICE_ID, args.deviceId);
3443 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3444 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3445 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3446 ASSERT_EQ(0, args.keyCode);
3447 ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
3448 ASSERT_EQ(AMETA_NONE, args.metaState);
3449 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3450 ASSERT_EQ(0U, args.policyFlags);
3451 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3452
3453 // Key up with unknown scan code or usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003454 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
3455 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_UNKNOWN, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003456 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3457 ASSERT_EQ(DEVICE_ID, args.deviceId);
3458 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3459 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3460 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3461 ASSERT_EQ(0, args.keyCode);
3462 ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
3463 ASSERT_EQ(AMETA_NONE, args.metaState);
3464 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3465 ASSERT_EQ(0U, args.policyFlags);
3466 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3467}
3468
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003469TEST_F(KeyboardInputMapperTest, Process_KeyRemapping) {
3470 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
3471 mFakeEventHub->addKey(EVENTHUB_ID, KEY_B, 0, AKEYCODE_B, 0);
3472 mFakeEventHub->addKeyRemapping(EVENTHUB_ID, AKEYCODE_A, AKEYCODE_B);
3473
3474 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003475 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003476 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
3477
3478 // Key down by scan code.
3479 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_A, 1);
3480 NotifyKeyArgs args;
3481 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3482 ASSERT_EQ(AKEYCODE_B, args.keyCode);
3483
3484 // Key up by scan code.
3485 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 0);
3486 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3487 ASSERT_EQ(AKEYCODE_B, args.keyCode);
3488}
3489
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003490/**
3491 * Ensure that the readTime is set to the time when the EV_KEY is received.
3492 */
3493TEST_F(KeyboardInputMapperTest, Process_SendsReadTime) {
3494 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3495
3496 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003497 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003498 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
3499 NotifyKeyArgs args;
3500
3501 // Key down
Harry Cutts33476232023-01-30 19:57:29 +00003502 process(mapper, ARBITRARY_TIME, /*readTime=*/12, EV_KEY, KEY_HOME, 1);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003503 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3504 ASSERT_EQ(12, args.readTime);
3505
3506 // Key up
Harry Cutts33476232023-01-30 19:57:29 +00003507 process(mapper, ARBITRARY_TIME, /*readTime=*/15, EV_KEY, KEY_HOME, 1);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003508 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3509 ASSERT_EQ(15, args.readTime);
3510}
3511
Michael Wrightd02c5b62014-02-10 15:10:22 -08003512TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003513 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFTSHIFT, 0, AKEYCODE_SHIFT_LEFT, 0);
3514 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
Chris Yea52ade12020-08-27 16:49:20 -07003515 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 0);
3516 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0);
3517 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003518
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003519 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003520 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003521 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003522
Arthur Hung95f68612022-04-07 14:08:22 +08003523 // Initial metastate is AMETA_NONE.
3524 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003525
3526 // Metakey down.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003527 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003528 NotifyKeyArgs args;
3529 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3530 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003531 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
arthurhungdcef2dc2020-08-11 14:47:50 +08003532 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003533
3534 // Key down.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003535 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003536 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3537 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003538 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003539
3540 // Key up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003541 process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_KEY, KEY_A, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003542 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3543 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003544 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003545
3546 // Metakey up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003547 process(mapper, ARBITRARY_TIME + 3, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003548 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3549 ASSERT_EQ(AMETA_NONE, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003550 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
arthurhungdcef2dc2020-08-11 14:47:50 +08003551 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003552}
3553
3554TEST_F(KeyboardInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateDPad) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003555 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3556 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3557 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3558 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003559
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003560 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003561 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003562 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003563
Michael Wrighta9cf4192022-12-01 23:46:39 +00003564 prepareDisplay(ui::ROTATION_90);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003565 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3566 KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
3567 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3568 KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
3569 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3570 KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
3571 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3572 KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
3573}
3574
3575TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003576 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3577 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3578 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3579 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003580
Michael Wrightd02c5b62014-02-10 15:10:22 -08003581 addConfigurationProperty("keyboard.orientationAware", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003582 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003583 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003584 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003585
Michael Wrighta9cf4192022-12-01 23:46:39 +00003586 prepareDisplay(ui::ROTATION_0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003587 ASSERT_NO_FATAL_FAILURE(
3588 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
3589 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3590 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3591 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3592 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3593 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3594 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003595
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003596 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003597 prepareDisplay(ui::ROTATION_90);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003598 ASSERT_NO_FATAL_FAILURE(
3599 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3600 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3601 AKEYCODE_DPAD_UP, DISPLAY_ID));
3602 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3603 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3604 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3605 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003606
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003607 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003608 prepareDisplay(ui::ROTATION_180);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003609 ASSERT_NO_FATAL_FAILURE(
3610 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3611 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3612 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3613 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3614 AKEYCODE_DPAD_UP, DISPLAY_ID));
3615 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3616 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003617
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003618 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003619 prepareDisplay(ui::ROTATION_270);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003620 ASSERT_NO_FATAL_FAILURE(
3621 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3622 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3623 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3624 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3625 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3626 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3627 AKEYCODE_DPAD_UP, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003628
3629 // Special case: if orientation changes while key is down, we still emit the same keycode
3630 // in the key up as we did in the key down.
3631 NotifyKeyArgs args;
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003632 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003633 prepareDisplay(ui::ROTATION_270);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003634 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003635 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3636 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3637 ASSERT_EQ(KEY_UP, args.scanCode);
3638 ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
3639
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003640 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003641 prepareDisplay(ui::ROTATION_180);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003642 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003643 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3644 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3645 ASSERT_EQ(KEY_UP, args.scanCode);
3646 ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
3647}
3648
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003649TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_NotOrientationAware) {
3650 // If the keyboard is not orientation aware,
3651 // key events should not be associated with a specific display id
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003652 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003653
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003654 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003655 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003656 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003657 NotifyKeyArgs args;
3658
3659 // Display id should be ADISPLAY_ID_NONE without any display configuration.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003660 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003661 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003662 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003663 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Linnan Li13bf76a2024-05-05 19:18:02 +08003664 ASSERT_EQ(ui::ADISPLAY_ID_NONE, args.displayId);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003665
Michael Wrighta9cf4192022-12-01 23:46:39 +00003666 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003667 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003668 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003669 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003670 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Linnan Li13bf76a2024-05-05 19:18:02 +08003671 ASSERT_EQ(ui::ADISPLAY_ID_NONE, args.displayId);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003672}
3673
3674TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_OrientationAware) {
3675 // If the keyboard is orientation aware,
3676 // key events should be associated with the internal viewport
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003677 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003678
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003679 addConfigurationProperty("keyboard.orientationAware", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003680 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003681 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003682 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003683 NotifyKeyArgs args;
3684
3685 // Display id should be ADISPLAY_ID_NONE without any display configuration.
3686 // ^--- 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 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003709 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003710 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003711
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003712 mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003713 ASSERT_EQ(1, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003714
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003715 mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003716 ASSERT_EQ(0, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003717}
3718
Philip Junker4af3b3d2021-12-14 10:36:55 +01003719TEST_F(KeyboardInputMapperTest, GetKeyCodeForKeyLocation) {
3720 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003721 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Philip Junker4af3b3d2021-12-14 10:36:55 +01003722 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
3723
3724 mFakeEventHub->addKeyCodeMapping(EVENTHUB_ID, AKEYCODE_Y, AKEYCODE_Z);
3725 ASSERT_EQ(AKEYCODE_Z, mapper.getKeyCodeForKeyLocation(AKEYCODE_Y))
3726 << "If a mapping is available, the result is equal to the mapping";
3727
3728 ASSERT_EQ(AKEYCODE_A, mapper.getKeyCodeForKeyLocation(AKEYCODE_A))
3729 << "If no mapping is available, the result is the key location";
3730}
3731
Michael Wrightd02c5b62014-02-10 15:10:22 -08003732TEST_F(KeyboardInputMapperTest, GetScanCodeState) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003733 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003734 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003735 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003736
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003737 mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003738 ASSERT_EQ(1, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003739
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003740 mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003741 ASSERT_EQ(0, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003742}
3743
3744TEST_F(KeyboardInputMapperTest, MarkSupportedKeyCodes) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003745 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003746 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003747 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003748
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003749 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003750
Michael Wrightd02c5b62014-02-10 15:10:22 -08003751 uint8_t flags[2] = { 0, 0 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07003752 ASSERT_TRUE(mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_A, AKEYCODE_B}, flags));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003753 ASSERT_TRUE(flags[0]);
3754 ASSERT_FALSE(flags[1]);
3755}
3756
3757TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003758 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3759 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3760 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3761 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3762 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3763 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003764
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003765 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003766 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003767 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Arthur Hung95f68612022-04-07 14:08:22 +08003768 // Initial metastate is AMETA_NONE.
3769 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003770
3771 // Initialization should have turned all of the lights off.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003772 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3773 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3774 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003775
3776 // Toggle caps lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003777 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3778 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003779 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3780 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3781 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003782 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003783
3784 // Toggle num lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003785 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3786 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003787 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3788 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3789 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003790 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003791
3792 // Toggle caps lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003793 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3794 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003795 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3796 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3797 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003798 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003799
3800 // Toggle scroll lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003801 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3802 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003803 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3804 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3805 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003806 ASSERT_EQ(AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003807
3808 // Toggle num lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003809 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3810 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003811 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3812 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3813 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003814 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003815
3816 // Toggle scroll lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003817 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3818 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003819 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3820 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3821 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003822 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003823}
3824
Chris Yea52ade12020-08-27 16:49:20 -07003825TEST_F(KeyboardInputMapperTest, NoMetaStateWhenMetaKeysNotPresent) {
3826 mFakeEventHub->addKey(EVENTHUB_ID, BTN_A, 0, AKEYCODE_BUTTON_A, 0);
3827 mFakeEventHub->addKey(EVENTHUB_ID, BTN_B, 0, AKEYCODE_BUTTON_B, 0);
3828 mFakeEventHub->addKey(EVENTHUB_ID, BTN_X, 0, AKEYCODE_BUTTON_X, 0);
3829 mFakeEventHub->addKey(EVENTHUB_ID, BTN_Y, 0, AKEYCODE_BUTTON_Y, 0);
3830
3831 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003832 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Chris Yea52ade12020-08-27 16:49:20 -07003833 AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC);
3834
Chris Yea52ade12020-08-27 16:49:20 -07003835 // Meta state should be AMETA_NONE after reset
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003836 std::list<NotifyArgs> unused = mapper.reset(ARBITRARY_TIME);
Chris Yea52ade12020-08-27 16:49:20 -07003837 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3838 // Meta state should be AMETA_NONE with update, as device doesn't have the keys.
3839 mapper.updateMetaState(AKEYCODE_NUM_LOCK);
3840 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3841
3842 NotifyKeyArgs args;
3843 // Press button "A"
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003844 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_A, 1);
Chris Yea52ade12020-08-27 16:49:20 -07003845 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3846 ASSERT_EQ(AMETA_NONE, args.metaState);
3847 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3848 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3849 ASSERT_EQ(AKEYCODE_BUTTON_A, args.keyCode);
3850
3851 // Button up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003852 process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_KEY, BTN_A, 0);
Chris Yea52ade12020-08-27 16:49:20 -07003853 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3854 ASSERT_EQ(AMETA_NONE, args.metaState);
3855 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3856 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3857 ASSERT_EQ(AKEYCODE_BUTTON_A, args.keyCode);
3858}
3859
Arthur Hung2c9a3342019-07-23 14:18:59 +08003860TEST_F(KeyboardInputMapperTest, Configure_AssignsDisplayPort) {
3861 // keyboard 1.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003862 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3863 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3864 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3865 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003866
3867 // keyboard 2.
3868 const std::string USB2 = "USB2";
arthurhungdcef2dc2020-08-11 14:47:50 +08003869 const std::string DEVICE_NAME2 = "KEYBOARD2";
Arthur Hung2c9a3342019-07-23 14:18:59 +08003870 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003871 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
arthurhungdcef2dc2020-08-11 14:47:50 +08003872 std::shared_ptr<InputDevice> device2 =
3873 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
Dominik Laskowski2f01d772022-03-23 16:01:29 -07003874 ftl::Flags<InputDeviceClass>(0));
arthurhungdcef2dc2020-08-11 14:47:50 +08003875
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003876 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3877 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3878 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3879 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003880
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003881 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003882 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003883 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003884
Arpit Singh67ca6842023-04-26 14:43:16 +00003885 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003886 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003887 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3888 mFakePolicy
3889 ->getReaderConfiguration(),
3890 AINPUT_SOURCE_KEYBOARD,
3891 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003892 std::list<NotifyArgs> unused =
3893 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003894 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003895 unused += device2->reset(ARBITRARY_TIME);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003896
3897 // Prepared displays and associated info.
3898 constexpr uint8_t hdmi1 = 0;
3899 constexpr uint8_t hdmi2 = 1;
3900 const std::string SECONDARY_UNIQUE_ID = "local:1";
3901
3902 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
3903 mFakePolicy->addInputPortAssociation(USB2, hdmi2);
3904
3905 // No associated display viewport found, should disable the device.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003906 unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003907 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003908 ASSERT_FALSE(device2->isEnabled());
3909
3910 // Prepare second display.
Linnan Li13bf76a2024-05-05 19:18:02 +08003911 constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
Michael Wrighta9cf4192022-12-01 23:46:39 +00003912 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003913 UNIQUE_ID, hdmi1, ViewportType::INTERNAL);
Michael Wrighta9cf4192022-12-01 23:46:39 +00003914 setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003915 SECONDARY_UNIQUE_ID, hdmi2, ViewportType::EXTERNAL);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003916 // Default device will reconfigure above, need additional reconfiguration for another device.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003917 unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003918 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003919
3920 // Device should be enabled after the associated display is found.
3921 ASSERT_TRUE(mDevice->isEnabled());
3922 ASSERT_TRUE(device2->isEnabled());
3923
3924 // Test pad key events
3925 ASSERT_NO_FATAL_FAILURE(
3926 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
3927 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3928 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3929 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3930 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3931 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3932 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3933
3934 ASSERT_NO_FATAL_FAILURE(
3935 testDPadKeyRotation(mapper2, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, newDisplayId));
3936 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3937 AKEYCODE_DPAD_RIGHT, newDisplayId));
3938 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3939 AKEYCODE_DPAD_DOWN, newDisplayId));
3940 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3941 AKEYCODE_DPAD_LEFT, newDisplayId));
3942}
Michael Wrightd02c5b62014-02-10 15:10:22 -08003943
arthurhungc903df12020-08-11 15:08:42 +08003944TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleAfterReattach) {
3945 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3946 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3947 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3948 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3949 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3950 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3951
3952 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003953 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
arthurhungc903df12020-08-11 15:08:42 +08003954 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Arthur Hung95f68612022-04-07 14:08:22 +08003955 // Initial metastate is AMETA_NONE.
3956 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
arthurhungc903df12020-08-11 15:08:42 +08003957
3958 // Initialization should have turned all of the lights off.
3959 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3960 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3961 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3962
3963 // Toggle caps lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003964 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3965 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003966 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3967 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
3968
3969 // Toggle num lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003970 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3971 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003972 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3973 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
3974
3975 // Toggle scroll lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003976 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3977 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003978 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3979 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
3980
3981 mFakeEventHub->removeDevice(EVENTHUB_ID);
3982 mReader->loopOnce();
3983
3984 // keyboard 2 should default toggle keys.
3985 const std::string USB2 = "USB2";
3986 const std::string DEVICE_NAME2 = "KEYBOARD2";
3987 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
3988 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
3989 std::shared_ptr<InputDevice> device2 =
3990 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
Dominik Laskowski2f01d772022-03-23 16:01:29 -07003991 ftl::Flags<InputDeviceClass>(0));
arthurhungc903df12020-08-11 15:08:42 +08003992 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3993 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
3994 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3995 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3996 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3997 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3998
Arpit Singh67ca6842023-04-26 14:43:16 +00003999 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
arthurhung6fe95782020-10-05 22:41:16 +08004000 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00004001 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
4002 mFakePolicy
4003 ->getReaderConfiguration(),
4004 AINPUT_SOURCE_KEYBOARD,
4005 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07004006 std::list<NotifyArgs> unused =
4007 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004008 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07004009 unused += device2->reset(ARBITRARY_TIME);
arthurhungc903df12020-08-11 15:08:42 +08004010
4011 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_CAPSL));
4012 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_NUML));
4013 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_SCROLLL));
arthurhung6fe95782020-10-05 22:41:16 +08004014 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON,
4015 mapper2.getMetaState());
arthurhungc903df12020-08-11 15:08:42 +08004016}
4017
Arthur Hungcb40a002021-08-03 14:31:01 +00004018TEST_F(KeyboardInputMapperTest, Process_toggleCapsLockState) {
4019 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
4020 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
4021 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
4022
4023 // Suppose we have two mappers. (DPAD + KEYBOARD)
Arpit Singh67ca6842023-04-26 14:43:16 +00004024 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD,
Arthur Hungcb40a002021-08-03 14:31:01 +00004025 AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC);
4026 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00004027 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Arthur Hungcb40a002021-08-03 14:31:01 +00004028 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Arthur Hung95f68612022-04-07 14:08:22 +08004029 // Initial metastate is AMETA_NONE.
4030 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Arthur Hungcb40a002021-08-03 14:31:01 +00004031
4032 mReader->toggleCapsLockState(DEVICE_ID);
4033 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
4034}
4035
Arthur Hungfb3cc112022-04-13 07:39:50 +00004036TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleInMultiDevices) {
4037 // keyboard 1.
4038 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
4039 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
4040 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
4041 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
4042 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
4043 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
4044
4045 KeyboardInputMapper& mapper1 =
Arpit Singh67ca6842023-04-26 14:43:16 +00004046 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Arthur Hungfb3cc112022-04-13 07:39:50 +00004047 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
4048
4049 // keyboard 2.
4050 const std::string USB2 = "USB2";
4051 const std::string DEVICE_NAME2 = "KEYBOARD2";
4052 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
4053 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
4054 std::shared_ptr<InputDevice> device2 =
4055 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
4056 ftl::Flags<InputDeviceClass>(0));
4057 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
4058 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
4059 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
4060 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
4061 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
4062 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
4063
Arpit Singh67ca6842023-04-26 14:43:16 +00004064 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
Arthur Hungfb3cc112022-04-13 07:39:50 +00004065 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00004066 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
4067 mFakePolicy
4068 ->getReaderConfiguration(),
4069 AINPUT_SOURCE_KEYBOARD,
4070 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07004071 std::list<NotifyArgs> unused =
4072 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004073 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07004074 unused += device2->reset(ARBITRARY_TIME);
Arthur Hungfb3cc112022-04-13 07:39:50 +00004075
Arthur Hung95f68612022-04-07 14:08:22 +08004076 // Initial metastate is AMETA_NONE.
4077 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
4078 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
4079
4080 // Toggle num lock on and off.
4081 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
4082 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Arthur Hungfb3cc112022-04-13 07:39:50 +00004083 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
4084 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper1.getMetaState());
4085 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper2.getMetaState());
4086
4087 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
4088 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
4089 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
4090 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
4091 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
4092
4093 // Toggle caps lock on and off.
4094 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
4095 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
4096 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
4097 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper1.getMetaState());
4098 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper2.getMetaState());
4099
4100 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
4101 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
4102 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
4103 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
4104 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
4105
4106 // Toggle scroll lock on and off.
4107 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
4108 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
4109 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
4110 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper1.getMetaState());
4111 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper2.getMetaState());
4112
4113 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
4114 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
4115 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
4116 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
4117 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
4118}
4119
Arthur Hung2141d542022-08-23 07:45:21 +00004120TEST_F(KeyboardInputMapperTest, Process_DisabledDevice) {
4121 const int32_t USAGE_A = 0x070004;
4122 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4123 mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
4124
4125 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00004126 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Arthur Hung2141d542022-08-23 07:45:21 +00004127 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
4128 // Key down by scan code.
4129 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
4130 NotifyKeyArgs args;
4131 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4132 ASSERT_EQ(DEVICE_ID, args.deviceId);
4133 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4134 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4135 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
4136 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4137 ASSERT_EQ(KEY_HOME, args.scanCode);
4138 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
4139
4140 // Disable device, it should synthesize cancellation events for down events.
4141 mFakePolicy->addDisabledDevice(DEVICE_ID);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004142 configureDevice(InputReaderConfiguration::Change::ENABLED_STATE);
Arthur Hung2141d542022-08-23 07:45:21 +00004143
4144 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4145 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
4146 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4147 ASSERT_EQ(KEY_HOME, args.scanCode);
4148 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_CANCELED, args.flags);
4149}
4150
Zixuan Qufecb6062022-11-12 04:44:31 +00004151TEST_F(KeyboardInputMapperTest, Configure_AssignKeyboardLayoutInfo) {
Arpit Singh67ca6842023-04-26 14:43:16 +00004152 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
4153 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Zixuan Qufecb6062022-11-12 04:44:31 +00004154 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004155 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
4156 /*changes=*/{});
Zixuan Qufecb6062022-11-12 04:44:31 +00004157
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +00004158 uint32_t generation = mReader->getContext()->getGeneration();
Zixuan Qufecb6062022-11-12 04:44:31 +00004159 mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
4160
4161 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004162 InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
Zixuan Qufecb6062022-11-12 04:44:31 +00004163
4164 InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
4165 ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.languageTag,
4166 deviceInfo.getKeyboardLayoutInfo()->languageTag);
4167 ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.layoutType,
4168 deviceInfo.getKeyboardLayoutInfo()->layoutType);
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +00004169 ASSERT_TRUE(mReader->getContext()->getGeneration() != generation);
4170
4171 // Call change layout association with the same values: Generation shouldn't change
4172 generation = mReader->getContext()->getGeneration();
4173 mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
4174 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
4175 InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
4176 ASSERT_TRUE(mReader->getContext()->getGeneration() == generation);
Zixuan Qufecb6062022-11-12 04:44:31 +00004177}
4178
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004179TEST_F(KeyboardInputMapperTest, LayoutInfoCorrectlyMapped) {
4180 mFakeEventHub->setRawLayoutInfo(EVENTHUB_ID,
4181 RawLayoutInfo{.languageTag = "en", .layoutType = "extended"});
4182
4183 // Configuration
Arpit Singh67ca6842023-04-26 14:43:16 +00004184 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004185 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
4186 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004187 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004188
4189 ASSERT_EQ("en", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->languageTag);
4190 ASSERT_EQ("extended", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->layoutType);
4191}
4192
Justin Chung71ddb432023-03-27 04:29:07 +00004193TEST_F(KeyboardInputMapperTest, Process_GesureEventToSetFlagKeepTouchMode) {
4194 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, POLICY_FLAG_GESTURE);
4195 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00004196 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Justin Chung71ddb432023-03-27 04:29:07 +00004197 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
4198 NotifyKeyArgs args;
4199
4200 // Key down
4201 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFT, 1);
4202 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4203 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_KEEP_TOUCH_MODE, args.flags);
4204}
4205
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004206// --- KeyboardInputMapperTest_ExternalDevice ---
4207
4208class KeyboardInputMapperTest_ExternalDevice : public InputMapperTest {
4209protected:
Chris Yea52ade12020-08-27 16:49:20 -07004210 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL); }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004211};
4212
Vaibhav Devmurari2681a812024-01-11 00:15:35 +00004213TEST_F(KeyboardInputMapperTest_ExternalDevice, WakeBehavior_AlphabeticKeyboard) {
Vaibhav Devmurari16257862023-03-06 10:06:32 +00004214 // For external devices, keys will trigger wake on key down. Media keys should also trigger
4215 // wake if triggered from external devices.
Powei Fengd041c5d2019-05-03 17:11:33 -07004216
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004217 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, 0);
4218 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
4219 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
4220 POLICY_FLAG_WAKE);
Powei Fengd041c5d2019-05-03 17:11:33 -07004221
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004222 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00004223 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004224 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Powei Fengd041c5d2019-05-03 17:11:33 -07004225
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004226 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004227 NotifyKeyArgs args;
4228 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4229 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4230
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004231 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004232 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4233 ASSERT_EQ(uint32_t(0), args.policyFlags);
4234
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004235 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004236 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Vaibhav Devmurari16257862023-03-06 10:06:32 +00004237 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
Powei Fengd041c5d2019-05-03 17:11:33 -07004238
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004239 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004240 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4241 ASSERT_EQ(uint32_t(0), args.policyFlags);
4242
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004243 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004244 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4245 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4246
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004247 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004248 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4249 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4250}
4251
Vaibhav Devmurari2681a812024-01-11 00:15:35 +00004252TEST_F(KeyboardInputMapperTest_ExternalDevice, WakeBehavior_NoneAlphabeticKeyboard) {
4253 // For external devices, keys will trigger wake on key down. Media keys should not trigger
4254 // wake if triggered from external non-alphaebtic keyboard (e.g. headsets).
4255
4256 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
4257 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
4258 POLICY_FLAG_WAKE);
4259
4260 KeyboardInputMapper& mapper =
4261 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
4262 AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC);
4263
4264 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
4265 NotifyKeyArgs args;
4266 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4267 ASSERT_EQ(uint32_t(0), args.policyFlags);
4268
4269 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
4270 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4271 ASSERT_EQ(uint32_t(0), args.policyFlags);
4272
4273 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1);
4274 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4275 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4276
4277 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0);
4278 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4279 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4280}
4281
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004282TEST_F(KeyboardInputMapperTest_ExternalDevice, DoNotWakeByDefaultBehavior) {
Powei Fengd041c5d2019-05-03 17:11:33 -07004283 // Tv Remote key's wake behavior is prescribed by the keylayout file.
Powei Fengd041c5d2019-05-03 17:11:33 -07004284
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004285 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4286 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
4287 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, POLICY_FLAG_WAKE);
Powei Fengd041c5d2019-05-03 17:11:33 -07004288
Powei Fengd041c5d2019-05-03 17:11:33 -07004289 addConfigurationProperty("keyboard.doNotWakeByDefault", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004290 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00004291 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004292 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Powei Fengd041c5d2019-05-03 17:11:33 -07004293
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004294 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004295 NotifyKeyArgs args;
4296 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4297 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4298
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004299 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004300 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4301 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4302
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004303 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_DOWN, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004304 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4305 ASSERT_EQ(uint32_t(0), args.policyFlags);
4306
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004307 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_DOWN, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004308 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4309 ASSERT_EQ(uint32_t(0), args.policyFlags);
4310
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004311 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004312 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4313 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4314
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004315 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004316 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4317 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4318}
4319
Michael Wrightd02c5b62014-02-10 15:10:22 -08004320// --- TouchInputMapperTest ---
4321
4322class TouchInputMapperTest : public InputMapperTest {
4323protected:
4324 static const int32_t RAW_X_MIN;
4325 static const int32_t RAW_X_MAX;
4326 static const int32_t RAW_Y_MIN;
4327 static const int32_t RAW_Y_MAX;
4328 static const int32_t RAW_TOUCH_MIN;
4329 static const int32_t RAW_TOUCH_MAX;
4330 static const int32_t RAW_TOOL_MIN;
4331 static const int32_t RAW_TOOL_MAX;
4332 static const int32_t RAW_PRESSURE_MIN;
4333 static const int32_t RAW_PRESSURE_MAX;
4334 static const int32_t RAW_ORIENTATION_MIN;
4335 static const int32_t RAW_ORIENTATION_MAX;
4336 static const int32_t RAW_DISTANCE_MIN;
4337 static const int32_t RAW_DISTANCE_MAX;
4338 static const int32_t RAW_TILT_MIN;
4339 static const int32_t RAW_TILT_MAX;
4340 static const int32_t RAW_ID_MIN;
4341 static const int32_t RAW_ID_MAX;
4342 static const int32_t RAW_SLOT_MIN;
4343 static const int32_t RAW_SLOT_MAX;
4344 static const float X_PRECISION;
4345 static const float Y_PRECISION;
Santos Cordonfa5cf462017-04-05 10:37:00 -07004346 static const float X_PRECISION_VIRTUAL;
4347 static const float Y_PRECISION_VIRTUAL;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004348
4349 static const float GEOMETRIC_SCALE;
Jason Gerecke489fda82012-09-07 17:19:40 -07004350 static const TouchAffineTransformation AFFINE_TRANSFORM;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004351
4352 static const VirtualKeyDefinition VIRTUAL_KEYS[2];
4353
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07004354 const std::string UNIQUE_ID = "local:0";
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004355 const std::string SECONDARY_UNIQUE_ID = "local:1";
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07004356
Michael Wrightd02c5b62014-02-10 15:10:22 -08004357 enum Axes {
4358 POSITION = 1 << 0,
4359 TOUCH = 1 << 1,
4360 TOOL = 1 << 2,
4361 PRESSURE = 1 << 3,
4362 ORIENTATION = 1 << 4,
4363 MINOR = 1 << 5,
4364 ID = 1 << 6,
4365 DISTANCE = 1 << 7,
4366 TILT = 1 << 8,
4367 SLOT = 1 << 9,
4368 TOOL_TYPE = 1 << 10,
4369 };
4370
Michael Wrighta9cf4192022-12-01 23:46:39 +00004371 void prepareDisplay(ui::Rotation orientation, std::optional<uint8_t> port = NO_PORT);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004372 void prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port = NO_PORT);
Michael Wrighta9cf4192022-12-01 23:46:39 +00004373 void prepareVirtualDisplay(ui::Rotation orientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004374 void prepareVirtualKeys();
Jason Gerecke489fda82012-09-07 17:19:40 -07004375 void prepareLocationCalibration();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004376 int32_t toRawX(float displayX);
4377 int32_t toRawY(float displayY);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07004378 int32_t toRotatedRawX(float displayX);
4379 int32_t toRotatedRawY(float displayY);
Jason Gerecke489fda82012-09-07 17:19:40 -07004380 float toCookedX(float rawX, float rawY);
4381 float toCookedY(float rawX, float rawY);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004382 float toDisplayX(int32_t rawX);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004383 float toDisplayX(int32_t rawX, int32_t displayWidth);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004384 float toDisplayY(int32_t rawY);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004385 float toDisplayY(int32_t rawY, int32_t displayHeight);
4386
Michael Wrightd02c5b62014-02-10 15:10:22 -08004387};
4388
4389const int32_t TouchInputMapperTest::RAW_X_MIN = 25;
4390const int32_t TouchInputMapperTest::RAW_X_MAX = 1019;
4391const int32_t TouchInputMapperTest::RAW_Y_MIN = 30;
4392const int32_t TouchInputMapperTest::RAW_Y_MAX = 1009;
4393const int32_t TouchInputMapperTest::RAW_TOUCH_MIN = 0;
4394const int32_t TouchInputMapperTest::RAW_TOUCH_MAX = 31;
4395const int32_t TouchInputMapperTest::RAW_TOOL_MIN = 0;
4396const int32_t TouchInputMapperTest::RAW_TOOL_MAX = 15;
Michael Wrightaa449c92017-12-13 21:21:43 +00004397const int32_t TouchInputMapperTest::RAW_PRESSURE_MIN = 0;
4398const int32_t TouchInputMapperTest::RAW_PRESSURE_MAX = 255;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004399const int32_t TouchInputMapperTest::RAW_ORIENTATION_MIN = -7;
4400const int32_t TouchInputMapperTest::RAW_ORIENTATION_MAX = 7;
4401const int32_t TouchInputMapperTest::RAW_DISTANCE_MIN = 0;
4402const int32_t TouchInputMapperTest::RAW_DISTANCE_MAX = 7;
4403const int32_t TouchInputMapperTest::RAW_TILT_MIN = 0;
4404const int32_t TouchInputMapperTest::RAW_TILT_MAX = 150;
4405const int32_t TouchInputMapperTest::RAW_ID_MIN = 0;
4406const int32_t TouchInputMapperTest::RAW_ID_MAX = 9;
4407const int32_t TouchInputMapperTest::RAW_SLOT_MIN = 0;
4408const int32_t TouchInputMapperTest::RAW_SLOT_MAX = 9;
4409const float TouchInputMapperTest::X_PRECISION = float(RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH;
4410const float TouchInputMapperTest::Y_PRECISION = float(RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT;
Santos Cordonfa5cf462017-04-05 10:37:00 -07004411const float TouchInputMapperTest::X_PRECISION_VIRTUAL =
4412 float(RAW_X_MAX - RAW_X_MIN + 1) / VIRTUAL_DISPLAY_WIDTH;
4413const float TouchInputMapperTest::Y_PRECISION_VIRTUAL =
4414 float(RAW_Y_MAX - RAW_Y_MIN + 1) / VIRTUAL_DISPLAY_HEIGHT;
Jason Gerecke489fda82012-09-07 17:19:40 -07004415const TouchAffineTransformation TouchInputMapperTest::AFFINE_TRANSFORM =
4416 TouchAffineTransformation(1, -2, 3, -4, 5, -6);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004417
4418const float TouchInputMapperTest::GEOMETRIC_SCALE =
4419 avg(float(DISPLAY_WIDTH) / (RAW_X_MAX - RAW_X_MIN + 1),
4420 float(DISPLAY_HEIGHT) / (RAW_Y_MAX - RAW_Y_MIN + 1));
4421
4422const VirtualKeyDefinition TouchInputMapperTest::VIRTUAL_KEYS[2] = {
4423 { KEY_HOME, 60, DISPLAY_HEIGHT + 15, 20, 20 },
4424 { KEY_MENU, DISPLAY_HEIGHT - 60, DISPLAY_WIDTH + 15, 20, 20 },
4425};
4426
Michael Wrighta9cf4192022-12-01 23:46:39 +00004427void TouchInputMapperTest::prepareDisplay(ui::Rotation orientation, std::optional<uint8_t> port) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01004428 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
4429 port, ViewportType::INTERNAL);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004430}
4431
4432void TouchInputMapperTest::prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port) {
4433 setDisplayInfoAndReconfigure(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00004434 ui::ROTATION_0, SECONDARY_UNIQUE_ID, port, type);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004435}
4436
Michael Wrighta9cf4192022-12-01 23:46:39 +00004437void TouchInputMapperTest::prepareVirtualDisplay(ui::Rotation orientation) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01004438 setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH, VIRTUAL_DISPLAY_HEIGHT,
4439 orientation, VIRTUAL_DISPLAY_UNIQUE_ID, NO_PORT,
4440 ViewportType::VIRTUAL);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004441}
4442
Michael Wrightd02c5b62014-02-10 15:10:22 -08004443void TouchInputMapperTest::prepareVirtualKeys() {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004444 mFakeEventHub->addVirtualKeyDefinition(EVENTHUB_ID, VIRTUAL_KEYS[0]);
4445 mFakeEventHub->addVirtualKeyDefinition(EVENTHUB_ID, VIRTUAL_KEYS[1]);
4446 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4447 mFakeEventHub->addKey(EVENTHUB_ID, KEY_MENU, 0, AKEYCODE_MENU, POLICY_FLAG_WAKE);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004448}
4449
Jason Gerecke489fda82012-09-07 17:19:40 -07004450void TouchInputMapperTest::prepareLocationCalibration() {
4451 mFakePolicy->setTouchAffineTransformation(AFFINE_TRANSFORM);
4452}
4453
Michael Wrightd02c5b62014-02-10 15:10:22 -08004454int32_t TouchInputMapperTest::toRawX(float displayX) {
4455 return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH + RAW_X_MIN);
4456}
4457
4458int32_t TouchInputMapperTest::toRawY(float displayY) {
4459 return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT + RAW_Y_MIN);
4460}
4461
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07004462int32_t TouchInputMapperTest::toRotatedRawX(float displayX) {
4463 return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_HEIGHT + RAW_X_MIN);
4464}
4465
4466int32_t TouchInputMapperTest::toRotatedRawY(float displayY) {
4467 return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_WIDTH + RAW_Y_MIN);
4468}
4469
Jason Gerecke489fda82012-09-07 17:19:40 -07004470float TouchInputMapperTest::toCookedX(float rawX, float rawY) {
4471 AFFINE_TRANSFORM.applyTo(rawX, rawY);
4472 return rawX;
4473}
4474
4475float TouchInputMapperTest::toCookedY(float rawX, float rawY) {
4476 AFFINE_TRANSFORM.applyTo(rawX, rawY);
4477 return rawY;
4478}
4479
Michael Wrightd02c5b62014-02-10 15:10:22 -08004480float TouchInputMapperTest::toDisplayX(int32_t rawX) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004481 return toDisplayX(rawX, DISPLAY_WIDTH);
4482}
4483
4484float TouchInputMapperTest::toDisplayX(int32_t rawX, int32_t displayWidth) {
4485 return float(rawX - RAW_X_MIN) * displayWidth / (RAW_X_MAX - RAW_X_MIN + 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004486}
4487
4488float TouchInputMapperTest::toDisplayY(int32_t rawY) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004489 return toDisplayY(rawY, DISPLAY_HEIGHT);
4490}
4491
4492float TouchInputMapperTest::toDisplayY(int32_t rawY, int32_t displayHeight) {
4493 return float(rawY - RAW_Y_MIN) * displayHeight / (RAW_Y_MAX - RAW_Y_MIN + 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004494}
4495
4496
4497// --- SingleTouchInputMapperTest ---
4498
4499class SingleTouchInputMapperTest : public TouchInputMapperTest {
4500protected:
4501 void prepareButtons();
4502 void prepareAxes(int axes);
4503
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004504 void processDown(SingleTouchInputMapper& mapper, int32_t x, int32_t y);
4505 void processMove(SingleTouchInputMapper& mapper, int32_t x, int32_t y);
4506 void processUp(SingleTouchInputMapper& mappery);
4507 void processPressure(SingleTouchInputMapper& mapper, int32_t pressure);
4508 void processToolMajor(SingleTouchInputMapper& mapper, int32_t toolMajor);
4509 void processDistance(SingleTouchInputMapper& mapper, int32_t distance);
4510 void processTilt(SingleTouchInputMapper& mapper, int32_t tiltX, int32_t tiltY);
4511 void processKey(SingleTouchInputMapper& mapper, int32_t code, int32_t value);
4512 void processSync(SingleTouchInputMapper& mapper);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004513};
4514
4515void SingleTouchInputMapperTest::prepareButtons() {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004516 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004517}
4518
4519void SingleTouchInputMapperTest::prepareAxes(int axes) {
4520 if (axes & POSITION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004521 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
4522 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004523 }
4524 if (axes & PRESSURE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004525 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_PRESSURE, RAW_PRESSURE_MIN,
4526 RAW_PRESSURE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004527 }
4528 if (axes & TOOL) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004529 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TOOL_WIDTH, RAW_TOOL_MIN, RAW_TOOL_MAX, 0,
4530 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004531 }
4532 if (axes & DISTANCE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004533 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_DISTANCE, RAW_DISTANCE_MIN,
4534 RAW_DISTANCE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004535 }
4536 if (axes & TILT) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004537 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TILT_X, RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
4538 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TILT_Y, RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004539 }
4540}
4541
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004542void SingleTouchInputMapperTest::processDown(SingleTouchInputMapper& mapper, int32_t x, int32_t y) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004543 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
4544 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, x);
4545 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, y);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004546}
4547
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004548void SingleTouchInputMapperTest::processMove(SingleTouchInputMapper& mapper, int32_t x, int32_t y) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004549 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, x);
4550 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, y);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004551}
4552
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004553void SingleTouchInputMapperTest::processUp(SingleTouchInputMapper& mapper) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004554 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004555}
4556
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004557void SingleTouchInputMapperTest::processPressure(SingleTouchInputMapper& mapper, int32_t pressure) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004558 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_PRESSURE, pressure);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004559}
4560
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004561void SingleTouchInputMapperTest::processToolMajor(SingleTouchInputMapper& mapper,
4562 int32_t toolMajor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004563 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TOOL_WIDTH, toolMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004564}
4565
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004566void SingleTouchInputMapperTest::processDistance(SingleTouchInputMapper& mapper, int32_t distance) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004567 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_DISTANCE, distance);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004568}
4569
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004570void SingleTouchInputMapperTest::processTilt(SingleTouchInputMapper& mapper, int32_t tiltX,
4571 int32_t tiltY) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004572 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TILT_X, tiltX);
4573 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TILT_Y, tiltY);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004574}
4575
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004576void SingleTouchInputMapperTest::processKey(SingleTouchInputMapper& mapper, int32_t code,
4577 int32_t value) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004578 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004579}
4580
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004581void SingleTouchInputMapperTest::processSync(SingleTouchInputMapper& mapper) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004582 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004583}
4584
Michael Wrightd02c5b62014-02-10 15:10:22 -08004585TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndNotACursor_ReturnsPointer) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004586 prepareButtons();
4587 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00004588 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004589
Josep del Río2d8c79a2023-01-23 19:33:50 +00004590 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004591}
4592
Michael Wrightd02c5b62014-02-10 15:10:22 -08004593TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004594 prepareButtons();
4595 prepareAxes(POSITION);
4596 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00004597 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004598
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004599 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004600}
4601
4602TEST_F(SingleTouchInputMapperTest, GetKeyCodeState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004603 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004604 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004605 prepareButtons();
4606 prepareAxes(POSITION);
4607 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004608 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004609
4610 // Unknown key.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004611 ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004612
4613 // Virtual key is down.
4614 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4615 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4616 processDown(mapper, x, y);
4617 processSync(mapper);
4618 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4619
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004620 ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004621
4622 // Virtual key is up.
4623 processUp(mapper);
4624 processSync(mapper);
4625 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4626
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004627 ASSERT_EQ(AKEY_STATE_UP, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004628}
4629
4630TEST_F(SingleTouchInputMapperTest, GetScanCodeState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004631 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004632 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004633 prepareButtons();
4634 prepareAxes(POSITION);
4635 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004636 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004637
4638 // Unknown key.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004639 ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004640
4641 // Virtual key is down.
4642 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4643 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4644 processDown(mapper, x, y);
4645 processSync(mapper);
4646 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4647
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004648 ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004649
4650 // Virtual key is up.
4651 processUp(mapper);
4652 processSync(mapper);
4653 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4654
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004655 ASSERT_EQ(AKEY_STATE_UP, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004656}
4657
4658TEST_F(SingleTouchInputMapperTest, MarkSupportedKeyCodes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004659 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004660 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004661 prepareButtons();
4662 prepareAxes(POSITION);
4663 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004664 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004665
Michael Wrightd02c5b62014-02-10 15:10:22 -08004666 uint8_t flags[2] = { 0, 0 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07004667 ASSERT_TRUE(
4668 mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_HOME, AKEYCODE_A}, flags));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004669 ASSERT_TRUE(flags[0]);
4670 ASSERT_FALSE(flags[1]);
4671}
4672
4673TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNormally_SendsKeyDownAndKeyUp) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004674 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004675 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004676 prepareButtons();
4677 prepareAxes(POSITION);
4678 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004679 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004680
arthurhungdcef2dc2020-08-11 14:47:50 +08004681 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004682
4683 NotifyKeyArgs args;
4684
4685 // Press virtual key.
4686 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4687 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4688 processDown(mapper, x, y);
4689 processSync(mapper);
4690
4691 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4692 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4693 ASSERT_EQ(DEVICE_ID, args.deviceId);
4694 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4695 ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
4696 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
4697 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
4698 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4699 ASSERT_EQ(KEY_HOME, args.scanCode);
4700 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
4701 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
4702
4703 // Release virtual key.
4704 processUp(mapper);
4705 processSync(mapper);
4706
4707 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4708 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4709 ASSERT_EQ(DEVICE_ID, args.deviceId);
4710 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4711 ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
4712 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
4713 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
4714 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4715 ASSERT_EQ(KEY_HOME, args.scanCode);
4716 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
4717 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
4718
4719 // Should not have sent any motions.
4720 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4721}
4722
4723TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfBounds_SendsKeyDownAndKeyCancel) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004724 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004725 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004726 prepareButtons();
4727 prepareAxes(POSITION);
4728 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004729 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004730
arthurhungdcef2dc2020-08-11 14:47:50 +08004731 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004732
4733 NotifyKeyArgs keyArgs;
4734
4735 // Press virtual key.
4736 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4737 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4738 processDown(mapper, x, y);
4739 processSync(mapper);
4740
4741 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
4742 ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
4743 ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
4744 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
4745 ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
4746 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
4747 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, keyArgs.flags);
4748 ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
4749 ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
4750 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
4751 ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
4752
4753 // Move out of bounds. This should generate a cancel and a pointer down since we moved
4754 // into the display area.
4755 y -= 100;
4756 processMove(mapper, x, y);
4757 processSync(mapper);
4758
4759 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
4760 ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
4761 ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
4762 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
4763 ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
4764 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
4765 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
4766 | AKEY_EVENT_FLAG_CANCELED, keyArgs.flags);
4767 ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
4768 ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
4769 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
4770 ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
4771
4772 NotifyMotionArgs motionArgs;
4773 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4774 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4775 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4776 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4777 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4778 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4779 ASSERT_EQ(0, motionArgs.flags);
4780 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4781 ASSERT_EQ(0, motionArgs.buttonState);
4782 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004783 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004784 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004785 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004786 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4787 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4788 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4789 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4790 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4791
4792 // Keep moving out of bounds. Should generate a pointer move.
4793 y -= 50;
4794 processMove(mapper, x, y);
4795 processSync(mapper);
4796
4797 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4798 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4799 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4800 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4801 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4802 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
4803 ASSERT_EQ(0, motionArgs.flags);
4804 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4805 ASSERT_EQ(0, motionArgs.buttonState);
4806 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004807 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004808 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004809 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004810 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4811 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4812 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4813 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4814 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4815
4816 // Release out of bounds. Should generate a pointer up.
4817 processUp(mapper);
4818 processSync(mapper);
4819
4820 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4821 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4822 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4823 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4824 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4825 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4826 ASSERT_EQ(0, motionArgs.flags);
4827 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4828 ASSERT_EQ(0, motionArgs.buttonState);
4829 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004830 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004831 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004832 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004833 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4834 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4835 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4836 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4837 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4838
4839 // Should not have sent any more keys or motions.
4840 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4841 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4842}
4843
4844TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMovesIn_SendsDownAsTouchEntersDisplay) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004845 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004846 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004847 prepareButtons();
4848 prepareAxes(POSITION);
4849 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004850 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004851
arthurhungdcef2dc2020-08-11 14:47:50 +08004852 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004853
4854 NotifyMotionArgs motionArgs;
4855
4856 // Initially go down out of bounds.
4857 int32_t x = -10;
4858 int32_t y = -10;
4859 processDown(mapper, x, y);
4860 processSync(mapper);
4861
4862 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4863
4864 // Move into the display area. Should generate a pointer down.
4865 x = 50;
4866 y = 75;
4867 processMove(mapper, x, y);
4868 processSync(mapper);
4869
4870 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4871 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4872 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4873 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4874 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4875 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4876 ASSERT_EQ(0, motionArgs.flags);
4877 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4878 ASSERT_EQ(0, motionArgs.buttonState);
4879 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004880 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004881 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004882 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004883 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4884 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4885 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4886 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4887 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4888
4889 // Release. Should generate a pointer up.
4890 processUp(mapper);
4891 processSync(mapper);
4892
4893 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4894 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4895 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4896 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4897 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4898 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4899 ASSERT_EQ(0, motionArgs.flags);
4900 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4901 ASSERT_EQ(0, motionArgs.buttonState);
4902 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004903 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004904 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004905 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004906 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4907 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4908 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4909 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4910 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4911
4912 // Should not have sent any more keys or motions.
4913 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4914 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4915}
4916
Santos Cordonfa5cf462017-04-05 10:37:00 -07004917TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture_VirtualDisplay) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004918 addConfigurationProperty("touch.deviceType", "touchScreen");
4919 addConfigurationProperty("touch.displayId", VIRTUAL_DISPLAY_UNIQUE_ID);
4920
Michael Wrighta9cf4192022-12-01 23:46:39 +00004921 prepareVirtualDisplay(ui::ROTATION_0);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004922 prepareButtons();
4923 prepareAxes(POSITION);
4924 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004925 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Santos Cordonfa5cf462017-04-05 10:37:00 -07004926
arthurhungdcef2dc2020-08-11 14:47:50 +08004927 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004928
4929 NotifyMotionArgs motionArgs;
4930
4931 // Down.
4932 int32_t x = 100;
4933 int32_t y = 125;
4934 processDown(mapper, x, y);
4935 processSync(mapper);
4936
4937 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4938 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4939 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4940 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4941 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4942 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4943 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4944 ASSERT_EQ(0, motionArgs.flags);
4945 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4946 ASSERT_EQ(0, motionArgs.buttonState);
4947 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004948 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004949 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004950 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004951 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4952 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4953 1, 0, 0, 0, 0, 0, 0, 0));
4954 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4955 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4956 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4957
4958 // Move.
4959 x += 50;
4960 y += 75;
4961 processMove(mapper, x, y);
4962 processSync(mapper);
4963
4964 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4965 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4966 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4967 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4968 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4969 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4970 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
4971 ASSERT_EQ(0, motionArgs.flags);
4972 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4973 ASSERT_EQ(0, motionArgs.buttonState);
4974 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004975 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004976 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004977 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004978 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4979 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4980 1, 0, 0, 0, 0, 0, 0, 0));
4981 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4982 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4983 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4984
4985 // Up.
4986 processUp(mapper);
4987 processSync(mapper);
4988
4989 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4990 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4991 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4992 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4993 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4994 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4995 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4996 ASSERT_EQ(0, motionArgs.flags);
4997 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4998 ASSERT_EQ(0, motionArgs.buttonState);
4999 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005000 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07005001 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005002 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07005003 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5004 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
5005 1, 0, 0, 0, 0, 0, 0, 0));
5006 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
5007 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
5008 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5009
5010 // Should not have sent any more keys or motions.
5011 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5012 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5013}
5014
Michael Wrightd02c5b62014-02-10 15:10:22 -08005015TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005016 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005017 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005018 prepareButtons();
5019 prepareAxes(POSITION);
5020 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00005021 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005022
arthurhungdcef2dc2020-08-11 14:47:50 +08005023 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005024
5025 NotifyMotionArgs motionArgs;
5026
5027 // Down.
5028 int32_t x = 100;
5029 int32_t y = 125;
5030 processDown(mapper, x, y);
5031 processSync(mapper);
5032
5033 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5034 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5035 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5036 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5037 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5038 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5039 ASSERT_EQ(0, motionArgs.flags);
5040 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5041 ASSERT_EQ(0, motionArgs.buttonState);
5042 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005043 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08005044 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005045 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005046 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5047 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
5048 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5049 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5050 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5051
5052 // Move.
5053 x += 50;
5054 y += 75;
5055 processMove(mapper, x, y);
5056 processSync(mapper);
5057
5058 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5059 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5060 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5061 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5062 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5063 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5064 ASSERT_EQ(0, motionArgs.flags);
5065 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5066 ASSERT_EQ(0, motionArgs.buttonState);
5067 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005068 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08005069 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005070 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005071 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5072 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
5073 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5074 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5075 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5076
5077 // Up.
5078 processUp(mapper);
5079 processSync(mapper);
5080
5081 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5082 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5083 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5084 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5085 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5086 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5087 ASSERT_EQ(0, motionArgs.flags);
5088 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5089 ASSERT_EQ(0, motionArgs.buttonState);
5090 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005091 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08005092 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005093 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005094 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5095 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
5096 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5097 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5098 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5099
5100 // Should not have sent any more keys or motions.
5101 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5102 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5103}
5104
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005105TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_DoesNotRotateMotions) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005106 addConfigurationProperty("touch.deviceType", "touchScreen");
5107 prepareButtons();
5108 prepareAxes(POSITION);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005109 // InputReader works in the un-rotated coordinate space, so orientation-aware devices do not
5110 // need to be rotated. Touchscreens are orientation-aware by default.
Arpit Singha8c236b2023-04-25 13:56:05 +00005111 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005112
5113 NotifyMotionArgs args;
5114
5115 // Rotation 90.
Michael Wrighta9cf4192022-12-01 23:46:39 +00005116 prepareDisplay(ui::ROTATION_90);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005117 processDown(mapper, toRawX(50), toRawY(75));
5118 processSync(mapper);
5119
5120 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5121 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5122 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5123
5124 processUp(mapper);
5125 processSync(mapper);
5126 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5127}
5128
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005129TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_RotatesMotions) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005130 addConfigurationProperty("touch.deviceType", "touchScreen");
5131 prepareButtons();
5132 prepareAxes(POSITION);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005133 // Since InputReader works in the un-rotated coordinate space, only devices that are not
5134 // orientation-aware are affected by display rotation.
5135 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00005136 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005137
5138 NotifyMotionArgs args;
5139
5140 // Rotation 0.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005141 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005142 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005143 processDown(mapper, toRawX(50), toRawY(75));
5144 processSync(mapper);
5145
5146 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5147 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5148 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5149
5150 processUp(mapper);
5151 processSync(mapper);
5152 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5153
5154 // Rotation 90.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005155 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005156 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005157 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005158 processSync(mapper);
5159
5160 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5161 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5162 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5163
5164 processUp(mapper);
5165 processSync(mapper);
5166 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5167
5168 // Rotation 180.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005169 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005170 prepareDisplay(ui::ROTATION_180);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005171 processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
5172 processSync(mapper);
5173
5174 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5175 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5176 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5177
5178 processUp(mapper);
5179 processSync(mapper);
5180 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5181
5182 // Rotation 270.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005183 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005184 prepareDisplay(ui::ROTATION_270);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005185 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005186 processSync(mapper);
5187
5188 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5189 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5190 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5191
5192 processUp(mapper);
5193 processSync(mapper);
5194 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5195}
5196
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005197TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation0_RotatesMotions) {
5198 addConfigurationProperty("touch.deviceType", "touchScreen");
5199 prepareButtons();
5200 prepareAxes(POSITION);
5201 addConfigurationProperty("touch.orientationAware", "1");
5202 addConfigurationProperty("touch.orientation", "ORIENTATION_0");
5203 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005204 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005205 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005206 NotifyMotionArgs args;
5207
5208 // Orientation 0.
5209 processDown(mapper, toRawX(50), toRawY(75));
5210 processSync(mapper);
5211
5212 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5213 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5214 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5215
5216 processUp(mapper);
5217 processSync(mapper);
5218 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5219}
5220
5221TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation90_RotatesMotions) {
5222 addConfigurationProperty("touch.deviceType", "touchScreen");
5223 prepareButtons();
5224 prepareAxes(POSITION);
5225 addConfigurationProperty("touch.orientationAware", "1");
5226 addConfigurationProperty("touch.orientation", "ORIENTATION_90");
5227 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005228 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005229 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005230 NotifyMotionArgs args;
5231
5232 // Orientation 90.
5233 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
5234 processSync(mapper);
5235
5236 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5237 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5238 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5239
5240 processUp(mapper);
5241 processSync(mapper);
5242 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5243}
5244
5245TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation180_RotatesMotions) {
5246 addConfigurationProperty("touch.deviceType", "touchScreen");
5247 prepareButtons();
5248 prepareAxes(POSITION);
5249 addConfigurationProperty("touch.orientationAware", "1");
5250 addConfigurationProperty("touch.orientation", "ORIENTATION_180");
5251 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005252 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005253 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005254 NotifyMotionArgs args;
5255
5256 // Orientation 180.
5257 processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
5258 processSync(mapper);
5259
5260 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5261 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5262 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5263
5264 processUp(mapper);
5265 processSync(mapper);
5266 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5267}
5268
5269TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation270_RotatesMotions) {
5270 addConfigurationProperty("touch.deviceType", "touchScreen");
5271 prepareButtons();
5272 prepareAxes(POSITION);
5273 addConfigurationProperty("touch.orientationAware", "1");
5274 addConfigurationProperty("touch.orientation", "ORIENTATION_270");
5275 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005276 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005277 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005278 NotifyMotionArgs args;
5279
5280 // Orientation 270.
5281 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
5282 processSync(mapper);
5283
5284 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5285 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5286 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5287
5288 processUp(mapper);
5289 processSync(mapper);
5290 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5291}
5292
5293TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationSpecified_RotatesMotionWithDisplay) {
5294 addConfigurationProperty("touch.deviceType", "touchScreen");
5295 prepareButtons();
5296 prepareAxes(POSITION);
5297 // Since InputReader works in the un-rotated coordinate space, only devices that are not
5298 // orientation-aware are affected by display rotation.
5299 addConfigurationProperty("touch.orientationAware", "0");
5300 addConfigurationProperty("touch.orientation", "ORIENTATION_90");
Arpit Singha8c236b2023-04-25 13:56:05 +00005301 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005302
5303 NotifyMotionArgs args;
5304
5305 // Orientation 90, Rotation 0.
5306 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005307 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005308 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
5309 processSync(mapper);
5310
5311 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5312 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5313 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5314
5315 processUp(mapper);
5316 processSync(mapper);
5317 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5318
5319 // Orientation 90, Rotation 90.
5320 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005321 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005322 processDown(mapper, toRawX(50), toRawY(75));
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005323 processSync(mapper);
5324
5325 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5326 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5327 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5328
5329 processUp(mapper);
5330 processSync(mapper);
5331 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5332
5333 // Orientation 90, Rotation 180.
5334 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005335 prepareDisplay(ui::ROTATION_180);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005336 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
5337 processSync(mapper);
5338
5339 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5340 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5341 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5342
5343 processUp(mapper);
5344 processSync(mapper);
5345 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5346
5347 // Orientation 90, Rotation 270.
5348 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005349 prepareDisplay(ui::ROTATION_270);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005350 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 -07005351 processSync(mapper);
5352
5353 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5354 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5355 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5356
5357 processUp(mapper);
5358 processSync(mapper);
5359 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5360}
5361
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005362TEST_F(SingleTouchInputMapperTest, Process_IgnoresTouchesOutsidePhysicalFrame) {
5363 addConfigurationProperty("touch.deviceType", "touchScreen");
5364 prepareButtons();
5365 prepareAxes(POSITION);
5366 addConfigurationProperty("touch.orientationAware", "1");
5367 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005368 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005369
5370 // Set a physical frame in the display viewport.
5371 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
5372 viewport->physicalLeft = 20;
5373 viewport->physicalTop = 600;
5374 viewport->physicalRight = 30;
5375 viewport->physicalBottom = 610;
5376 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00005377 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005378
5379 // Start the touch.
5380 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
5381 processSync(mapper);
5382
5383 // Expect all input starting outside the physical frame to be ignored.
5384 const std::array<Point, 6> outsidePoints = {
5385 {{0, 0}, {19, 605}, {31, 605}, {25, 599}, {25, 611}, {DISPLAY_WIDTH, DISPLAY_HEIGHT}}};
5386 for (const auto& p : outsidePoints) {
5387 processMove(mapper, toRawX(p.x), toRawY(p.y));
5388 processSync(mapper);
5389 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5390 }
5391
5392 // Move the touch into the physical frame.
5393 processMove(mapper, toRawX(25), toRawY(605));
5394 processSync(mapper);
5395 NotifyMotionArgs args;
5396 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5397 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
5398 EXPECT_NEAR(25, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5399 EXPECT_NEAR(605, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5400
5401 // Once the touch down is reported, continue reporting input, even if it is outside the frame.
5402 for (const auto& p : outsidePoints) {
5403 processMove(mapper, toRawX(p.x), toRawY(p.y));
5404 processSync(mapper);
5405 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5406 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
5407 EXPECT_NEAR(p.x, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5408 EXPECT_NEAR(p.y, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5409 }
5410
5411 processUp(mapper);
5412 processSync(mapper);
5413 EXPECT_NO_FATAL_FAILURE(
5414 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
5415}
5416
Harry Cutts1db43992023-06-19 17:05:07 +00005417TEST_F(SingleTouchInputMapperTest, Process_DoesntCheckPhysicalFrameForTouchpads) {
Harry Cutts1db43992023-06-19 17:05:07 +00005418 addConfigurationProperty("touch.deviceType", "pointer");
5419 prepareAxes(POSITION);
5420 prepareDisplay(ui::ROTATION_0);
5421 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
5422
5423 // Set a physical frame in the display viewport.
5424 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
5425 viewport->physicalLeft = 20;
5426 viewport->physicalTop = 600;
5427 viewport->physicalRight = 30;
5428 viewport->physicalBottom = 610;
5429 mFakePolicy->updateViewport(*viewport);
5430 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
5431
5432 // Start the touch.
5433 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
5434 processSync(mapper);
5435
5436 // Expect all input starting outside the physical frame to result in NotifyMotionArgs being
5437 // produced.
5438 const std::array<Point, 6> outsidePoints = {
5439 {{0, 0}, {19, 605}, {31, 605}, {25, 599}, {25, 611}, {DISPLAY_WIDTH, DISPLAY_HEIGHT}}};
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());
5444 }
5445}
5446
Michael Wrightd02c5b62014-02-10 15:10:22 -08005447TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005448 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005449 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005450 prepareButtons();
5451 prepareAxes(POSITION | PRESSURE | TOOL | DISTANCE | TILT);
Arpit Singha8c236b2023-04-25 13:56:05 +00005452 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005453
5454 // These calculations are based on the input device calibration documentation.
5455 int32_t rawX = 100;
5456 int32_t rawY = 200;
5457 int32_t rawPressure = 10;
5458 int32_t rawToolMajor = 12;
5459 int32_t rawDistance = 2;
5460 int32_t rawTiltX = 30;
5461 int32_t rawTiltY = 110;
5462
5463 float x = toDisplayX(rawX);
5464 float y = toDisplayY(rawY);
5465 float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
5466 float size = float(rawToolMajor) / RAW_TOOL_MAX;
5467 float tool = float(rawToolMajor) * GEOMETRIC_SCALE;
5468 float distance = float(rawDistance);
5469
5470 float tiltCenter = (RAW_TILT_MAX + RAW_TILT_MIN) * 0.5f;
5471 float tiltScale = M_PI / 180;
5472 float tiltXAngle = (rawTiltX - tiltCenter) * tiltScale;
5473 float tiltYAngle = (rawTiltY - tiltCenter) * tiltScale;
5474 float orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
5475 float tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
5476
5477 processDown(mapper, rawX, rawY);
5478 processPressure(mapper, rawPressure);
5479 processToolMajor(mapper, rawToolMajor);
5480 processDistance(mapper, rawDistance);
5481 processTilt(mapper, rawTiltX, rawTiltY);
5482 processSync(mapper);
5483
5484 NotifyMotionArgs args;
5485 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5486 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
5487 x, y, pressure, size, tool, tool, tool, tool, orientation, distance));
5488 ASSERT_EQ(tilt, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TILT));
5489}
5490
Jason Gerecke489fda82012-09-07 17:19:40 -07005491TEST_F(SingleTouchInputMapperTest, Process_XYAxes_AffineCalibration) {
Jason Gerecke489fda82012-09-07 17:19:40 -07005492 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005493 prepareDisplay(ui::ROTATION_0);
Jason Gerecke489fda82012-09-07 17:19:40 -07005494 prepareLocationCalibration();
5495 prepareButtons();
5496 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005497 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Jason Gerecke489fda82012-09-07 17:19:40 -07005498
5499 int32_t rawX = 100;
5500 int32_t rawY = 200;
5501
5502 float x = toDisplayX(toCookedX(rawX, rawY));
5503 float y = toDisplayY(toCookedY(rawX, rawY));
5504
5505 processDown(mapper, rawX, rawY);
5506 processSync(mapper);
5507
5508 NotifyMotionArgs args;
5509 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5510 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
5511 x, y, 1, 0, 0, 0, 0, 0, 0, 0));
5512}
5513
Michael Wrightd02c5b62014-02-10 15:10:22 -08005514TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllButtons) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005515 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005516 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005517 prepareButtons();
5518 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005519 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005520
5521 NotifyMotionArgs motionArgs;
5522 NotifyKeyArgs keyArgs;
5523
5524 processDown(mapper, 100, 200);
5525 processSync(mapper);
5526 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5527 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5528 ASSERT_EQ(0, motionArgs.buttonState);
5529
5530 // press BTN_LEFT, release BTN_LEFT
5531 processKey(mapper, BTN_LEFT, 1);
5532 processSync(mapper);
5533 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5534 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5535 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
5536
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005537 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5538 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5539 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
5540
Michael Wrightd02c5b62014-02-10 15:10:22 -08005541 processKey(mapper, BTN_LEFT, 0);
5542 processSync(mapper);
5543 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005544 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005545 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005546
5547 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005548 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005549 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005550
5551 // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
5552 processKey(mapper, BTN_RIGHT, 1);
5553 processKey(mapper, BTN_MIDDLE, 1);
5554 processSync(mapper);
5555 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5556 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5557 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
5558 motionArgs.buttonState);
5559
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005560 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5561 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5562 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
5563
5564 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5565 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5566 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
5567 motionArgs.buttonState);
5568
Michael Wrightd02c5b62014-02-10 15:10:22 -08005569 processKey(mapper, BTN_RIGHT, 0);
5570 processSync(mapper);
5571 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005572 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005573 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005574
5575 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005576 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005577 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005578
5579 processKey(mapper, BTN_MIDDLE, 0);
5580 processSync(mapper);
5581 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005582 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005583 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005584
5585 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005586 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005587 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005588
5589 // press BTN_BACK, release BTN_BACK
5590 processKey(mapper, BTN_BACK, 1);
5591 processSync(mapper);
5592 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5593 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5594 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005595
Michael Wrightd02c5b62014-02-10 15:10:22 -08005596 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005597 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005598 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
5599
5600 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5601 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5602 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005603
5604 processKey(mapper, BTN_BACK, 0);
5605 processSync(mapper);
5606 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005607 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005608 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005609
5610 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005611 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005612 ASSERT_EQ(0, motionArgs.buttonState);
5613
Michael Wrightd02c5b62014-02-10 15:10:22 -08005614 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5615 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5616 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
5617
5618 // press BTN_SIDE, release BTN_SIDE
5619 processKey(mapper, BTN_SIDE, 1);
5620 processSync(mapper);
5621 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5622 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5623 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005624
Michael Wrightd02c5b62014-02-10 15:10:22 -08005625 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005626 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005627 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
5628
5629 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5630 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5631 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005632
5633 processKey(mapper, BTN_SIDE, 0);
5634 processSync(mapper);
5635 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005636 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005637 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005638
5639 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005640 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005641 ASSERT_EQ(0, motionArgs.buttonState);
5642
Michael Wrightd02c5b62014-02-10 15:10:22 -08005643 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5644 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5645 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
5646
5647 // press BTN_FORWARD, release BTN_FORWARD
5648 processKey(mapper, BTN_FORWARD, 1);
5649 processSync(mapper);
5650 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5651 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5652 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005653
Michael Wrightd02c5b62014-02-10 15:10:22 -08005654 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005655 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005656 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
5657
5658 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5659 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5660 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005661
5662 processKey(mapper, BTN_FORWARD, 0);
5663 processSync(mapper);
5664 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005665 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005666 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005667
5668 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005669 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005670 ASSERT_EQ(0, motionArgs.buttonState);
5671
Michael Wrightd02c5b62014-02-10 15:10:22 -08005672 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5673 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5674 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
5675
5676 // press BTN_EXTRA, release BTN_EXTRA
5677 processKey(mapper, BTN_EXTRA, 1);
5678 processSync(mapper);
5679 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5680 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5681 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005682
Michael Wrightd02c5b62014-02-10 15:10:22 -08005683 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005684 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005685 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
5686
5687 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5688 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5689 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005690
5691 processKey(mapper, BTN_EXTRA, 0);
5692 processSync(mapper);
5693 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005694 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005695 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005696
5697 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005698 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005699 ASSERT_EQ(0, motionArgs.buttonState);
5700
Michael Wrightd02c5b62014-02-10 15:10:22 -08005701 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5702 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5703 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
5704
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005705 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5706
Michael Wrightd02c5b62014-02-10 15:10:22 -08005707 // press BTN_STYLUS, release BTN_STYLUS
5708 processKey(mapper, BTN_STYLUS, 1);
5709 processSync(mapper);
5710 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5711 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005712 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
5713
5714 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5715 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5716 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005717
5718 processKey(mapper, BTN_STYLUS, 0);
5719 processSync(mapper);
5720 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005721 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005722 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005723
5724 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(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005727
5728 // press BTN_STYLUS2, release BTN_STYLUS2
5729 processKey(mapper, BTN_STYLUS2, 1);
5730 processSync(mapper);
5731 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5732 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005733 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
5734
5735 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5736 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5737 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005738
5739 processKey(mapper, BTN_STYLUS2, 0);
5740 processSync(mapper);
5741 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005742 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005743 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005744
5745 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005746 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005747 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005748
5749 // release touch
5750 processUp(mapper);
5751 processSync(mapper);
5752 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5753 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5754 ASSERT_EQ(0, motionArgs.buttonState);
5755}
5756
5757TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005758 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005759 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005760 prepareButtons();
5761 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005762 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005763
5764 NotifyMotionArgs motionArgs;
5765
5766 // default tool type is finger
5767 processDown(mapper, 100, 200);
5768 processSync(mapper);
5769 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5770 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005771 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005772
5773 // eraser
5774 processKey(mapper, BTN_TOOL_RUBBER, 1);
5775 processSync(mapper);
5776 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5777 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005778 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005779
5780 // stylus
5781 processKey(mapper, BTN_TOOL_RUBBER, 0);
5782 processKey(mapper, BTN_TOOL_PEN, 1);
5783 processSync(mapper);
5784 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5785 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005786 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005787
5788 // brush
5789 processKey(mapper, BTN_TOOL_PEN, 0);
5790 processKey(mapper, BTN_TOOL_BRUSH, 1);
5791 processSync(mapper);
5792 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5793 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005794 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005795
5796 // pencil
5797 processKey(mapper, BTN_TOOL_BRUSH, 0);
5798 processKey(mapper, BTN_TOOL_PENCIL, 1);
5799 processSync(mapper);
5800 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5801 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005802 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005803
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08005804 // air-brush
Michael Wrightd02c5b62014-02-10 15:10:22 -08005805 processKey(mapper, BTN_TOOL_PENCIL, 0);
5806 processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
5807 processSync(mapper);
5808 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5809 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005810 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005811
5812 // mouse
5813 processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
5814 processKey(mapper, BTN_TOOL_MOUSE, 1);
5815 processSync(mapper);
5816 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5817 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005818 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005819
5820 // lens
5821 processKey(mapper, BTN_TOOL_MOUSE, 0);
5822 processKey(mapper, BTN_TOOL_LENS, 1);
5823 processSync(mapper);
5824 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5825 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005826 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005827
5828 // double-tap
5829 processKey(mapper, BTN_TOOL_LENS, 0);
5830 processKey(mapper, BTN_TOOL_DOUBLETAP, 1);
5831 processSync(mapper);
5832 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5833 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005834 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005835
5836 // triple-tap
5837 processKey(mapper, BTN_TOOL_DOUBLETAP, 0);
5838 processKey(mapper, BTN_TOOL_TRIPLETAP, 1);
5839 processSync(mapper);
5840 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5841 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005842 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005843
5844 // quad-tap
5845 processKey(mapper, BTN_TOOL_TRIPLETAP, 0);
5846 processKey(mapper, BTN_TOOL_QUADTAP, 1);
5847 processSync(mapper);
5848 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5849 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005850 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005851
5852 // finger
5853 processKey(mapper, BTN_TOOL_QUADTAP, 0);
5854 processKey(mapper, BTN_TOOL_FINGER, 1);
5855 processSync(mapper);
5856 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5857 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005858 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005859
5860 // stylus trumps finger
5861 processKey(mapper, BTN_TOOL_PEN, 1);
5862 processSync(mapper);
5863 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5864 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005865 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005866
5867 // eraser trumps stylus
5868 processKey(mapper, BTN_TOOL_RUBBER, 1);
5869 processSync(mapper);
5870 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5871 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005872 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005873
5874 // mouse trumps eraser
5875 processKey(mapper, BTN_TOOL_MOUSE, 1);
5876 processSync(mapper);
5877 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5878 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005879 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005880
5881 // back to default tool type
5882 processKey(mapper, BTN_TOOL_MOUSE, 0);
5883 processKey(mapper, BTN_TOOL_RUBBER, 0);
5884 processKey(mapper, BTN_TOOL_PEN, 0);
5885 processKey(mapper, BTN_TOOL_FINGER, 0);
5886 processSync(mapper);
5887 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5888 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005889 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005890}
5891
5892TEST_F(SingleTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005893 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005894 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005895 prepareButtons();
5896 prepareAxes(POSITION);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08005897 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_FINGER, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005898 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005899
5900 NotifyMotionArgs motionArgs;
5901
5902 // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0
5903 processKey(mapper, BTN_TOOL_FINGER, 1);
5904 processMove(mapper, 100, 200);
5905 processSync(mapper);
5906 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5907 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5908 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5909 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5910
5911 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5912 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5913 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5914 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5915
5916 // move a little
5917 processMove(mapper, 150, 250);
5918 processSync(mapper);
5919 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5920 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5921 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5922 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5923
5924 // down when BTN_TOUCH is pressed, pressure defaults to 1
5925 processKey(mapper, BTN_TOUCH, 1);
5926 processSync(mapper);
5927 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5928 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5929 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5930 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5931
5932 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5933 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5934 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5935 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5936
5937 // up when BTN_TOUCH is released, hover restored
5938 processKey(mapper, BTN_TOUCH, 0);
5939 processSync(mapper);
5940 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5941 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5942 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5943 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5944
5945 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5946 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5947 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5948 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5949
5950 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5951 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5952 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5953 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5954
5955 // exit hover when pointer goes away
5956 processKey(mapper, BTN_TOOL_FINGER, 0);
5957 processSync(mapper);
5958 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5959 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5960 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5961 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5962}
5963
5964TEST_F(SingleTouchInputMapperTest, Process_WhenAbsPressureIsPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005965 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005966 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005967 prepareButtons();
5968 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00005969 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005970
5971 NotifyMotionArgs motionArgs;
5972
5973 // initially hovering because pressure is 0
5974 processDown(mapper, 100, 200);
5975 processPressure(mapper, 0);
5976 processSync(mapper);
5977 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5978 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5979 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5980 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5981
5982 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5983 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5984 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5985 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5986
5987 // move a little
5988 processMove(mapper, 150, 250);
5989 processSync(mapper);
5990 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5991 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5992 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5993 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5994
5995 // down when pressure is non-zero
5996 processPressure(mapper, RAW_PRESSURE_MAX);
5997 processSync(mapper);
5998 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5999 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
6000 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6001 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6002
6003 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6004 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6005 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6006 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
6007
6008 // up when pressure becomes 0, hover restored
6009 processPressure(mapper, 0);
6010 processSync(mapper);
6011 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6012 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
6013 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6014 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
6015
6016 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6017 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
6018 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6019 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6020
6021 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6022 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
6023 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6024 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6025
6026 // exit hover when pointer goes away
6027 processUp(mapper);
6028 processSync(mapper);
6029 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6030 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
6031 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6032 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6033}
6034
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006035TEST_F(SingleTouchInputMapperTest, Reset_CancelsOngoingGesture) {
6036 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006037 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006038 prepareButtons();
6039 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00006040 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006041
6042 // Touch down.
6043 processDown(mapper, 100, 200);
6044 processPressure(mapper, 1);
6045 processSync(mapper);
6046 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6047 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
6048
6049 // Reset the mapper. This should cancel the ongoing gesture.
6050 resetMapper(mapper, ARBITRARY_TIME);
6051 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6052 WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
6053
6054 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6055}
6056
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006057TEST_F(SingleTouchInputMapperTest, Reset_RecreatesTouchState) {
6058 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006059 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006060 prepareButtons();
6061 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00006062 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006063
6064 // Set the initial state for the touch pointer.
6065 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_X, 100);
6066 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_Y, 200);
6067 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_PRESSURE, RAW_PRESSURE_MAX);
6068 mFakeEventHub->setScanCodeState(EVENTHUB_ID, BTN_TOUCH, 1);
6069
6070 // Reset the mapper. When the mapper is reset, we expect it to attempt to recreate the touch
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006071 // state by reading the current axis values. Since there was no ongoing gesture, calling reset
6072 // does not generate any events.
6073 resetMapper(mapper, ARBITRARY_TIME);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006074
6075 // Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
6076 // the recreated touch state to generate a down event.
6077 processSync(mapper);
6078 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6079 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPressure(1.f))));
6080
6081 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6082}
6083
lilinnan687e58f2022-07-19 16:00:50 +08006084TEST_F(SingleTouchInputMapperTest,
6085 Process_WhenViewportDisplayIdChanged_TouchIsCanceledAndDeviceIsReset) {
6086 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006087 prepareDisplay(ui::ROTATION_0);
lilinnan687e58f2022-07-19 16:00:50 +08006088 prepareButtons();
6089 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006090 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
lilinnan687e58f2022-07-19 16:00:50 +08006091 NotifyMotionArgs motionArgs;
6092
6093 // Down.
Prabir Pradhan3e5ec702022-07-29 16:26:24 +00006094 processDown(mapper, 100, 200);
lilinnan687e58f2022-07-19 16:00:50 +08006095 processSync(mapper);
6096
6097 // We should receive a down event
6098 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6099 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6100
6101 // Change display id
6102 clearViewports();
6103 prepareSecondaryDisplay(ViewportType::INTERNAL);
6104
6105 // We should receive a cancel event
6106 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6107 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
6108 // Then receive reset called
6109 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6110}
6111
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006112TEST_F(SingleTouchInputMapperTest,
6113 Process_WhenViewportActiveStatusChanged_TouchIsCanceledAndDeviceIsReset) {
6114 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006115 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006116 prepareButtons();
6117 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006118 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006119 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6120 NotifyMotionArgs motionArgs;
6121
6122 // Start a new gesture.
6123 processDown(mapper, 100, 200);
6124 processSync(mapper);
6125 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6126 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6127
6128 // Make the viewport inactive. This will put the device in disabled mode.
6129 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6130 viewport->isActive = false;
6131 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006132 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006133
6134 // We should receive a cancel event for the ongoing gesture.
6135 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6136 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
6137 // Then we should be notified that the device was reset.
6138 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6139
6140 // No events are generated while the viewport is inactive.
6141 processMove(mapper, 101, 201);
6142 processSync(mapper);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006143 processUp(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006144 processSync(mapper);
6145 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6146
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006147 // Start a new gesture while the viewport is still inactive.
6148 processDown(mapper, 300, 400);
6149 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_X, 300);
6150 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_Y, 400);
6151 mFakeEventHub->setScanCodeState(EVENTHUB_ID, BTN_TOUCH, 1);
6152 processSync(mapper);
6153
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006154 // Make the viewport active again. The device should resume processing events.
6155 viewport->isActive = true;
6156 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006157 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006158
6159 // The device is reset because it changes back to direct mode, without generating any events.
6160 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6161 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6162
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006163 // In the next sync, the touch state that was recreated when the device was reset is reported.
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006164 processSync(mapper);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006165 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6166 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006167
6168 // No more events.
6169 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6170 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
6171}
6172
Prabir Pradhan211ba622022-10-31 21:09:21 +00006173TEST_F(SingleTouchInputMapperTest, ButtonIsReleasedOnTouchUp) {
6174 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006175 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan211ba622022-10-31 21:09:21 +00006176 prepareButtons();
6177 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006178 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan211ba622022-10-31 21:09:21 +00006179 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6180
6181 // Press a stylus button.
6182 processKey(mapper, BTN_STYLUS, 1);
6183 processSync(mapper);
6184
6185 // Start a touch gesture and ensure the BUTTON_PRESS event is generated.
6186 processDown(mapper, 100, 200);
6187 processSync(mapper);
6188 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6189 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6190 WithCoords(toDisplayX(100), toDisplayY(200)),
6191 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6192 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6193 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
6194 WithCoords(toDisplayX(100), toDisplayY(200)),
6195 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6196
6197 // Release the touch gesture. Ensure that the BUTTON_RELEASE event is generated even though
6198 // the button has not actually been released, since there will be no pointers through which the
6199 // button state can be reported. The event is generated at the location of the pointer before
6200 // it went up.
6201 processUp(mapper);
6202 processSync(mapper);
6203 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6204 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
6205 WithCoords(toDisplayX(100), toDisplayY(200)), WithButtonState(0))));
6206 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6207 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6208 WithCoords(toDisplayX(100), toDisplayY(200)), WithButtonState(0))));
6209}
6210
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00006211TEST_F(SingleTouchInputMapperTest, StylusButtonMotionEventsDisabled) {
6212 addConfigurationProperty("touch.deviceType", "touchScreen");
6213 prepareDisplay(ui::ROTATION_0);
6214 prepareButtons();
6215 prepareAxes(POSITION);
6216
6217 mFakePolicy->setStylusButtonMotionEventsEnabled(false);
6218
Arpit Singha8c236b2023-04-25 13:56:05 +00006219 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +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 that the stylus button is not reported.
6227 processDown(mapper, 100, 200);
6228 processSync(mapper);
6229 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6230 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithButtonState(0))));
6231
6232 // Release and press the stylus button again.
6233 processKey(mapper, BTN_STYLUS, 0);
6234 processSync(mapper);
6235 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6236 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
6237 processKey(mapper, BTN_STYLUS, 1);
6238 processSync(mapper);
6239 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6240 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
6241
6242 // Release the touch gesture.
6243 processUp(mapper);
6244 processSync(mapper);
6245 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6246 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
6247
6248 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6249}
6250
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006251TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsSetToTouchNavigation_setsCorrectType) {
6252 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
6253 prepareDisplay(ui::ROTATION_0);
6254 prepareButtons();
6255 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006256 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006257 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6258
6259 ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION, mapper.getSources());
6260}
6261
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006262TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsChangedToTouchNavigation_updatesDeviceType) {
6263 // Initialize the device without setting device source to touch navigation.
6264 addConfigurationProperty("touch.deviceType", "touchScreen");
6265 prepareDisplay(ui::ROTATION_0);
6266 prepareButtons();
6267 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006268 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006269
6270 // Ensure that the device is created as a touchscreen, not touch navigation.
6271 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
6272
6273 // Add device type association after the device was created.
6274 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
6275
6276 // Send update to the mapper.
6277 std::list<NotifyArgs> unused2 =
6278 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006279 InputReaderConfiguration::Change::DEVICE_TYPE /*changes*/);
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006280
6281 // Check whether device type update was successful.
6282 ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION, mDevice->getSources());
6283}
6284
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006285TEST_F(SingleTouchInputMapperTest, HoverEventsOutsidePhysicalFrameAreIgnored) {
6286 // Initialize the device without setting device source to touch navigation.
6287 addConfigurationProperty("touch.deviceType", "touchScreen");
6288 prepareDisplay(ui::ROTATION_0);
6289 prepareButtons();
6290 prepareAxes(POSITION);
6291 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
6292
6293 // Set a physical frame in the display viewport.
6294 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6295 viewport->physicalLeft = 0;
6296 viewport->physicalTop = 0;
6297 viewport->physicalRight = DISPLAY_WIDTH / 2;
6298 viewport->physicalBottom = DISPLAY_HEIGHT / 2;
6299 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006300 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006301
Arpit Singha8c236b2023-04-25 13:56:05 +00006302 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006303
6304 // Hovering inside the physical frame produces events.
6305 processKey(mapper, BTN_TOOL_PEN, 1);
6306 processMove(mapper, RAW_X_MIN + 1, RAW_Y_MIN + 1);
6307 processSync(mapper);
6308 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6309 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)));
6310 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6311 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)));
6312
6313 // Leaving the physical frame ends the hovering gesture.
6314 processMove(mapper, RAW_X_MAX - 1, RAW_Y_MAX - 1);
6315 processSync(mapper);
6316 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6317 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT)));
6318
6319 // Moving outside the physical frame does not produce events.
6320 processMove(mapper, RAW_X_MAX - 2, RAW_Y_MAX - 2);
6321 processSync(mapper);
6322 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6323
6324 // Re-entering the physical frame produces events.
6325 processMove(mapper, RAW_X_MIN, RAW_Y_MIN);
6326 processSync(mapper);
6327 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6328 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)));
6329 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6330 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)));
6331}
6332
Prabir Pradhan5632d622021-09-06 07:57:20 -07006333// --- TouchDisplayProjectionTest ---
6334
6335class TouchDisplayProjectionTest : public SingleTouchInputMapperTest {
6336public:
6337 // The values inside DisplayViewport are expected to be pre-rotated. This updates the current
6338 // DisplayViewport to pre-rotate the values. The viewport's physical display will be set to the
6339 // rotated equivalent of the given un-rotated physical display bounds.
Prabir Pradhana9df3162022-12-05 23:57:27 +00006340 void configurePhysicalDisplay(ui::Rotation orientation, Rect naturalPhysicalDisplay,
6341 int32_t naturalDisplayWidth = DISPLAY_WIDTH,
6342 int32_t naturalDisplayHeight = DISPLAY_HEIGHT) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006343 uint32_t inverseRotationFlags;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006344 auto rotatedWidth = naturalDisplayWidth;
6345 auto rotatedHeight = naturalDisplayHeight;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006346 switch (orientation) {
Michael Wrighta9cf4192022-12-01 23:46:39 +00006347 case ui::ROTATION_90:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006348 inverseRotationFlags = ui::Transform::ROT_270;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006349 std::swap(rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006350 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006351 case ui::ROTATION_180:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006352 inverseRotationFlags = ui::Transform::ROT_180;
6353 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006354 case ui::ROTATION_270:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006355 inverseRotationFlags = ui::Transform::ROT_90;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006356 std::swap(rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006357 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006358 case ui::ROTATION_0:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006359 inverseRotationFlags = ui::Transform::ROT_0;
6360 break;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006361 }
6362
Prabir Pradhana9df3162022-12-05 23:57:27 +00006363 const ui::Transform rotation(inverseRotationFlags, rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006364 const Rect rotatedPhysicalDisplay = rotation.transform(naturalPhysicalDisplay);
6365
6366 std::optional<DisplayViewport> internalViewport =
6367 *mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6368 DisplayViewport& v = *internalViewport;
6369 v.displayId = DISPLAY_ID;
6370 v.orientation = orientation;
6371
6372 v.logicalLeft = 0;
6373 v.logicalTop = 0;
6374 v.logicalRight = 100;
6375 v.logicalBottom = 100;
6376
6377 v.physicalLeft = rotatedPhysicalDisplay.left;
6378 v.physicalTop = rotatedPhysicalDisplay.top;
6379 v.physicalRight = rotatedPhysicalDisplay.right;
6380 v.physicalBottom = rotatedPhysicalDisplay.bottom;
6381
Prabir Pradhana9df3162022-12-05 23:57:27 +00006382 v.deviceWidth = rotatedWidth;
6383 v.deviceHeight = rotatedHeight;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006384
6385 v.isActive = true;
6386 v.uniqueId = UNIQUE_ID;
6387 v.type = ViewportType::INTERNAL;
6388 mFakePolicy->updateViewport(v);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006389 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006390 }
6391
6392 void assertReceivedMove(const Point& point) {
6393 NotifyMotionArgs motionArgs;
6394 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6395 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006396 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Prabir Pradhan5632d622021-09-06 07:57:20 -07006397 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], point.x, point.y,
6398 1, 0, 0, 0, 0, 0, 0, 0));
6399 }
6400};
6401
6402TEST_F(TouchDisplayProjectionTest, IgnoresTouchesOutsidePhysicalDisplay) {
6403 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006404 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006405
6406 prepareButtons();
6407 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006408 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan5632d622021-09-06 07:57:20 -07006409
6410 NotifyMotionArgs motionArgs;
6411
6412 // Configure the DisplayViewport such that the logical display maps to a subsection of
6413 // the display panel called the physical display. Here, the physical display is bounded by the
6414 // points (10, 20) and (70, 160) inside the display space, which is of the size 400 x 800.
6415 static const Rect kPhysicalDisplay{10, 20, 70, 160};
6416 static const std::array<Point, 6> kPointsOutsidePhysicalDisplay{
6417 {{-10, -10}, {0, 0}, {5, 100}, {50, 15}, {75, 100}, {50, 165}}};
6418
Michael Wrighta9cf4192022-12-01 23:46:39 +00006419 for (auto orientation : {ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180, ui::ROTATION_270}) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006420 configurePhysicalDisplay(orientation, kPhysicalDisplay);
6421
6422 // Touches outside the physical display should be ignored, and should not generate any
6423 // events. Ensure touches at the following points that lie outside of the physical display
6424 // area do not generate any events.
6425 for (const auto& point : kPointsOutsidePhysicalDisplay) {
6426 processDown(mapper, toRawX(point.x), toRawY(point.y));
6427 processSync(mapper);
6428 processUp(mapper);
6429 processSync(mapper);
6430 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled())
6431 << "Unexpected event generated for touch outside physical display at point: "
6432 << point.x << ", " << point.y;
6433 }
6434 }
6435}
6436
6437TEST_F(TouchDisplayProjectionTest, EmitsTouchDownAfterEnteringPhysicalDisplay) {
6438 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006439 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006440
6441 prepareButtons();
6442 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006443 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan5632d622021-09-06 07:57:20 -07006444
6445 NotifyMotionArgs motionArgs;
6446
6447 // Configure the DisplayViewport such that the logical display maps to a subsection of
6448 // the display panel called the physical display. Here, the physical display is bounded by the
6449 // points (10, 20) and (70, 160) inside the display space, which is of the size 400 x 800.
6450 static const Rect kPhysicalDisplay{10, 20, 70, 160};
6451
Michael Wrighta9cf4192022-12-01 23:46:39 +00006452 for (auto orientation : {ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180, ui::ROTATION_270}) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006453 configurePhysicalDisplay(orientation, kPhysicalDisplay);
6454
6455 // Touches that start outside the physical display should be ignored until it enters the
6456 // physical display bounds, at which point it should generate a down event. Start a touch at
6457 // the point (5, 100), which is outside the physical display bounds.
6458 static const Point kOutsidePoint{5, 100};
6459 processDown(mapper, toRawX(kOutsidePoint.x), toRawY(kOutsidePoint.y));
6460 processSync(mapper);
6461 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6462
6463 // Move the touch into the physical display area. This should generate a pointer down.
6464 processMove(mapper, toRawX(11), toRawY(21));
6465 processSync(mapper);
6466 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6467 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006468 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Prabir Pradhan5632d622021-09-06 07:57:20 -07006469 ASSERT_NO_FATAL_FAILURE(
6470 assertPointerCoords(motionArgs.pointerCoords[0], 11, 21, 1, 0, 0, 0, 0, 0, 0, 0));
6471
6472 // Move the touch inside the physical display area. This should generate a pointer move.
6473 processMove(mapper, toRawX(69), toRawY(159));
6474 processSync(mapper);
6475 assertReceivedMove({69, 159});
6476
6477 // Move outside the physical display area. Since the pointer is already down, this should
6478 // now continue generating events.
6479 processMove(mapper, toRawX(kOutsidePoint.x), toRawY(kOutsidePoint.y));
6480 processSync(mapper);
6481 assertReceivedMove(kOutsidePoint);
6482
6483 // Release. This should generate a pointer up.
6484 processUp(mapper);
6485 processSync(mapper);
6486 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6487 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
6488 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], kOutsidePoint.x,
6489 kOutsidePoint.y, 1, 0, 0, 0, 0, 0, 0, 0));
6490
6491 // Ensure no more events were generated.
6492 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
6493 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6494 }
6495}
6496
Prabir Pradhana9df3162022-12-05 23:57:27 +00006497// --- TouchscreenPrecisionTests ---
6498
6499// This test suite is used to ensure that touchscreen devices are scaled and configured correctly
6500// in various orientations and with different display rotations. We configure the touchscreen to
6501// have a higher resolution than that of the display by an integer scale factor in each axis so that
6502// we can enforce that coordinates match precisely as expected.
6503class TouchscreenPrecisionTestsFixture : public TouchDisplayProjectionTest,
6504 public ::testing::WithParamInterface<ui::Rotation> {
6505public:
6506 void SetUp() override {
6507 SingleTouchInputMapperTest::SetUp();
6508
6509 // Prepare the raw axes to have twice the resolution of the display in the X axis and
6510 // four times the resolution of the display in the Y axis.
6511 prepareButtons();
6512 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, PRECISION_RAW_X_MIN, PRECISION_RAW_X_MAX,
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006513 PRECISION_RAW_X_FLAT, PRECISION_RAW_X_FUZZ,
6514 PRECISION_RAW_X_RES);
Prabir Pradhana9df3162022-12-05 23:57:27 +00006515 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, PRECISION_RAW_Y_MIN, PRECISION_RAW_Y_MAX,
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006516 PRECISION_RAW_Y_FLAT, PRECISION_RAW_Y_FUZZ,
6517 PRECISION_RAW_Y_RES);
Prabir Pradhana9df3162022-12-05 23:57:27 +00006518 }
6519
6520 static const int32_t PRECISION_RAW_X_MIN = TouchInputMapperTest::RAW_X_MIN;
6521 static const int32_t PRECISION_RAW_X_MAX = PRECISION_RAW_X_MIN + DISPLAY_WIDTH * 2 - 1;
6522 static const int32_t PRECISION_RAW_Y_MIN = TouchInputMapperTest::RAW_Y_MIN;
6523 static const int32_t PRECISION_RAW_Y_MAX = PRECISION_RAW_Y_MIN + DISPLAY_HEIGHT * 4 - 1;
6524
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006525 static const int32_t PRECISION_RAW_X_RES = 50; // units per millimeter
6526 static const int32_t PRECISION_RAW_Y_RES = 100; // units per millimeter
6527
6528 static const int32_t PRECISION_RAW_X_FLAT = 16;
6529 static const int32_t PRECISION_RAW_Y_FLAT = 32;
6530
6531 static const int32_t PRECISION_RAW_X_FUZZ = 4;
6532 static const int32_t PRECISION_RAW_Y_FUZZ = 8;
6533
Prabir Pradhana9df3162022-12-05 23:57:27 +00006534 static const std::array<Point, 4> kRawCorners;
6535};
6536
6537const std::array<Point, 4> TouchscreenPrecisionTestsFixture::kRawCorners = {{
6538 {PRECISION_RAW_X_MIN, PRECISION_RAW_Y_MIN}, // left-top
6539 {PRECISION_RAW_X_MAX, PRECISION_RAW_Y_MIN}, // right-top
6540 {PRECISION_RAW_X_MAX, PRECISION_RAW_Y_MAX}, // right-bottom
6541 {PRECISION_RAW_X_MIN, PRECISION_RAW_Y_MAX}, // left-bottom
6542}};
6543
6544// Tests for how the touchscreen is oriented relative to the natural orientation of the display.
6545// For example, if a touchscreen is configured with an orientation of 90 degrees, it is a portrait
6546// touchscreen panel that is used on a device whose natural display orientation is in landscape.
6547TEST_P(TouchscreenPrecisionTestsFixture, OrientationPrecision) {
6548 enum class Orientation {
6549 ORIENTATION_0 = ui::toRotationInt(ui::ROTATION_0),
6550 ORIENTATION_90 = ui::toRotationInt(ui::ROTATION_90),
6551 ORIENTATION_180 = ui::toRotationInt(ui::ROTATION_180),
6552 ORIENTATION_270 = ui::toRotationInt(ui::ROTATION_270),
6553 ftl_last = ORIENTATION_270,
6554 };
6555 using Orientation::ORIENTATION_0, Orientation::ORIENTATION_90, Orientation::ORIENTATION_180,
6556 Orientation::ORIENTATION_270;
6557 static const std::map<Orientation, std::array<vec2, 4> /*mappedCorners*/> kMappedCorners = {
6558 {ORIENTATION_0, {{{0, 0}, {479.5, 0}, {479.5, 799.75}, {0, 799.75}}}},
6559 {ORIENTATION_90, {{{0, 479.5}, {0, 0}, {799.75, 0}, {799.75, 479.5}}}},
6560 {ORIENTATION_180, {{{479.5, 799.75}, {0, 799.75}, {0, 0}, {479.5, 0}}}},
6561 {ORIENTATION_270, {{{799.75, 0}, {799.75, 479.5}, {0, 479.5}, {0, 0}}}},
6562 };
6563
6564 const auto touchscreenOrientation = static_cast<Orientation>(ui::toRotationInt(GetParam()));
6565
6566 // Configure the touchscreen as being installed in the one of the four different orientations
6567 // relative to the display.
6568 addConfigurationProperty("touch.deviceType", "touchScreen");
6569 addConfigurationProperty("touch.orientation", ftl::enum_string(touchscreenOrientation).c_str());
6570 prepareDisplay(ui::ROTATION_0);
6571
Arpit Singha8c236b2023-04-25 13:56:05 +00006572 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhana9df3162022-12-05 23:57:27 +00006573
6574 // If the touchscreen is installed in a rotated orientation relative to the display (i.e. in
6575 // orientations of either 90 or 270) this means the display's natural resolution will be
6576 // flipped.
6577 const bool displayRotated =
6578 touchscreenOrientation == ORIENTATION_90 || touchscreenOrientation == ORIENTATION_270;
6579 const int32_t width = displayRotated ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
6580 const int32_t height = displayRotated ? DISPLAY_WIDTH : DISPLAY_HEIGHT;
6581 const Rect physicalFrame{0, 0, width, height};
6582 configurePhysicalDisplay(ui::ROTATION_0, physicalFrame, width, height);
6583
6584 const auto& expectedPoints = kMappedCorners.at(touchscreenOrientation);
6585 const float expectedPrecisionX = displayRotated ? 4 : 2;
6586 const float expectedPrecisionY = displayRotated ? 2 : 4;
6587
6588 // Test all four corners.
6589 for (int i = 0; i < 4; i++) {
6590 const auto& raw = kRawCorners[i];
6591 processDown(mapper, raw.x, raw.y);
6592 processSync(mapper);
6593 const auto& expected = expectedPoints[i];
6594 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6595 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6596 WithCoords(expected.x, expected.y),
6597 WithPrecision(expectedPrecisionX, expectedPrecisionY))))
6598 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6599 << "with touchscreen orientation "
6600 << ftl::enum_string(touchscreenOrientation).c_str() << ", expected point ("
6601 << expected.x << ", " << expected.y << ").";
6602 processUp(mapper);
6603 processSync(mapper);
6604 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6605 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6606 WithCoords(expected.x, expected.y))));
6607 }
6608}
6609
Prabir Pradhan82687402022-12-06 01:32:53 +00006610TEST_P(TouchscreenPrecisionTestsFixture, RotationPrecisionWhenOrientationAware) {
6611 static const std::map<ui::Rotation /*rotation*/, std::array<vec2, 4> /*mappedCorners*/>
6612 kMappedCorners = {
6613 {ui::ROTATION_0, {{{0, 0}, {479.5, 0}, {479.5, 799.75}, {0, 799.75}}}},
6614 {ui::ROTATION_90, {{{0.5, 0}, {480, 0}, {480, 799.75}, {0.5, 799.75}}}},
6615 {ui::ROTATION_180, {{{0.5, 0.25}, {480, 0.25}, {480, 800}, {0.5, 800}}}},
6616 {ui::ROTATION_270, {{{0, 0.25}, {479.5, 0.25}, {479.5, 800}, {0, 800}}}},
6617 };
6618
6619 const ui::Rotation displayRotation = GetParam();
6620
6621 addConfigurationProperty("touch.deviceType", "touchScreen");
6622 prepareDisplay(displayRotation);
6623
Arpit Singha8c236b2023-04-25 13:56:05 +00006624 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan82687402022-12-06 01:32:53 +00006625
6626 const auto& expectedPoints = kMappedCorners.at(displayRotation);
6627
6628 // Test all four corners.
6629 for (int i = 0; i < 4; i++) {
6630 const auto& expected = expectedPoints[i];
6631 const auto& raw = kRawCorners[i];
6632 processDown(mapper, raw.x, raw.y);
6633 processSync(mapper);
6634 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6635 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6636 WithCoords(expected.x, expected.y), WithPrecision(2, 4))))
6637 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6638 << "with display rotation " << ui::toCString(displayRotation)
6639 << ", expected point (" << expected.x << ", " << expected.y << ").";
6640 processUp(mapper);
6641 processSync(mapper);
6642 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6643 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6644 WithCoords(expected.x, expected.y))));
6645 }
6646}
6647
Prabir Pradhan3e798762022-12-02 21:02:11 +00006648TEST_P(TouchscreenPrecisionTestsFixture, RotationPrecisionOrientationAwareInOri270) {
6649 static const std::map<ui::Rotation /*orientation*/, std::array<vec2, 4> /*mappedCorners*/>
6650 kMappedCorners = {
6651 {ui::ROTATION_0, {{{799.75, 0}, {799.75, 479.5}, {0, 479.5}, {0, 0}}}},
6652 {ui::ROTATION_90, {{{800, 0}, {800, 479.5}, {0.25, 479.5}, {0.25, 0}}}},
6653 {ui::ROTATION_180, {{{800, 0.5}, {800, 480}, {0.25, 480}, {0.25, 0.5}}}},
6654 {ui::ROTATION_270, {{{799.75, 0.5}, {799.75, 480}, {0, 480}, {0, 0.5}}}},
6655 };
6656
6657 const ui::Rotation displayRotation = GetParam();
6658
6659 addConfigurationProperty("touch.deviceType", "touchScreen");
6660 addConfigurationProperty("touch.orientation", "ORIENTATION_270");
6661
Arpit Singha8c236b2023-04-25 13:56:05 +00006662 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan3e798762022-12-02 21:02:11 +00006663
6664 // Ori 270, so width and height swapped
6665 const Rect physicalFrame{0, 0, DISPLAY_HEIGHT, DISPLAY_WIDTH};
6666 prepareDisplay(displayRotation);
6667 configurePhysicalDisplay(displayRotation, physicalFrame, DISPLAY_HEIGHT, DISPLAY_WIDTH);
6668
6669 const auto& expectedPoints = kMappedCorners.at(displayRotation);
6670
6671 // Test all four corners.
6672 for (int i = 0; i < 4; i++) {
6673 const auto& expected = expectedPoints[i];
6674 const auto& raw = kRawCorners[i];
6675 processDown(mapper, raw.x, raw.y);
6676 processSync(mapper);
6677 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6678 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6679 WithCoords(expected.x, expected.y), WithPrecision(4, 2))))
6680 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6681 << "with display rotation " << ui::toCString(displayRotation)
6682 << ", expected point (" << expected.x << ", " << expected.y << ").";
6683 processUp(mapper);
6684 processSync(mapper);
6685 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6686 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6687 WithCoords(expected.x, expected.y))));
6688 }
6689}
6690
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006691TEST_P(TouchscreenPrecisionTestsFixture, MotionRangesAreOrientedInRotatedDisplay) {
6692 const ui::Rotation displayRotation = GetParam();
6693
6694 addConfigurationProperty("touch.deviceType", "touchScreen");
6695 prepareDisplay(displayRotation);
6696
6697 __attribute__((unused)) SingleTouchInputMapper& mapper =
Arpit Singha8c236b2023-04-25 13:56:05 +00006698 constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006699
6700 const InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
6701 // MotionRanges use display pixels as their units
6702 const auto* xRange = deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHSCREEN);
6703 const auto* yRange = deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_Y, AINPUT_SOURCE_TOUCHSCREEN);
6704
6705 // The MotionRanges should be oriented in the rotated display's coordinate space
6706 const bool displayRotated =
6707 displayRotation == ui::ROTATION_90 || displayRotation == ui::ROTATION_270;
6708
6709 constexpr float MAX_X = 479.5;
6710 constexpr float MAX_Y = 799.75;
6711 EXPECT_EQ(xRange->min, 0.f);
6712 EXPECT_EQ(yRange->min, 0.f);
6713 EXPECT_EQ(xRange->max, displayRotated ? MAX_Y : MAX_X);
6714 EXPECT_EQ(yRange->max, displayRotated ? MAX_X : MAX_Y);
6715
6716 EXPECT_EQ(xRange->flat, 8.f);
6717 EXPECT_EQ(yRange->flat, 8.f);
6718
6719 EXPECT_EQ(xRange->fuzz, 2.f);
6720 EXPECT_EQ(yRange->fuzz, 2.f);
6721
6722 EXPECT_EQ(xRange->resolution, 25.f); // pixels per millimeter
6723 EXPECT_EQ(yRange->resolution, 25.f); // pixels per millimeter
6724}
6725
Prabir Pradhana9df3162022-12-05 23:57:27 +00006726// Run the precision tests for all rotations.
6727INSTANTIATE_TEST_SUITE_P(TouchscreenPrecisionTests, TouchscreenPrecisionTestsFixture,
6728 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
6729 ui::ROTATION_270),
6730 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
6731 return ftl::enum_string(testParamInfo.param);
6732 });
6733
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006734// --- ExternalStylusFusionTest ---
6735
6736class ExternalStylusFusionTest : public SingleTouchInputMapperTest {
6737public:
6738 SingleTouchInputMapper& initializeInputMapperWithExternalStylus() {
6739 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006740 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006741 prepareButtons();
6742 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006743 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006744
6745 mStylusState.when = ARBITRARY_TIME;
6746 mStylusState.pressure = 0.f;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006747 mStylusState.toolType = ToolType::STYLUS;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006748 mReader->getContext()->setExternalStylusDevices({mExternalStylusDeviceInfo});
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006749 configureDevice(InputReaderConfiguration::Change::EXTERNAL_STYLUS_PRESENCE);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006750 processExternalStylusState(mapper);
6751 return mapper;
6752 }
6753
6754 std::list<NotifyArgs> processExternalStylusState(InputMapper& mapper) {
6755 std::list<NotifyArgs> generatedArgs = mapper.updateExternalStylusState(mStylusState);
6756 for (const NotifyArgs& args : generatedArgs) {
6757 mFakeListener->notify(args);
6758 }
6759 // Loop the reader to flush the input listener queue.
6760 mReader->loopOnce();
6761 return generatedArgs;
6762 }
6763
6764protected:
6765 StylusState mStylusState{};
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006766
6767 void testStartFusedStylusGesture(SingleTouchInputMapper& mapper) {
6768 auto toolTypeSource =
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006769 AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006770
6771 // The first pointer is withheld.
6772 processDown(mapper, 100, 200);
6773 processSync(mapper);
6774 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6775 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6776 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6777
6778 // The external stylus reports pressure. The withheld finger pointer is released as a
6779 // stylus.
6780 mStylusState.pressure = 1.f;
6781 processExternalStylusState(mapper);
6782 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6783 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6784 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6785
6786 // Subsequent pointer events are not withheld.
6787 processMove(mapper, 101, 201);
6788 processSync(mapper);
6789 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6790 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6791
6792 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6793 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6794 }
6795
6796 void testSuccessfulFusionGesture(SingleTouchInputMapper& mapper) {
6797 ASSERT_NO_FATAL_FAILURE(testStartFusedStylusGesture(mapper));
6798
6799 // Releasing the touch pointer ends the gesture.
6800 processUp(mapper);
6801 processSync(mapper);
6802 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006803 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(STYLUS_FUSION_SOURCE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006804 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006805
6806 mStylusState.pressure = 0.f;
6807 processExternalStylusState(mapper);
6808 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6809 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6810 }
6811
6812 void testUnsuccessfulFusionGesture(SingleTouchInputMapper& mapper) {
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006813 // When stylus fusion is not successful, events should be reported with the original source.
6814 // In this case, it is from a touchscreen.
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006815 auto toolTypeSource =
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006816 AllOf(WithSource(AINPUT_SOURCE_TOUCHSCREEN), WithToolType(ToolType::FINGER));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006817
6818 // The first pointer is withheld when an external stylus is connected,
6819 // and a timeout is requested.
6820 processDown(mapper, 100, 200);
6821 processSync(mapper);
6822 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6823 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6824 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6825
6826 // If the timeout expires early, it is requested again.
6827 handleTimeout(mapper, ARBITRARY_TIME + 1);
6828 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6829 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6830
6831 // When the timeout expires, the withheld touch is released as a finger pointer.
6832 handleTimeout(mapper, ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT);
6833 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6834 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6835
6836 // Subsequent pointer events are not withheld.
6837 processMove(mapper, 101, 201);
6838 processSync(mapper);
6839 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6840 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6841 processUp(mapper);
6842 processSync(mapper);
6843 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6844 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP))));
6845
6846 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6847 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6848 }
6849
6850private:
6851 InputDeviceInfo mExternalStylusDeviceInfo{};
6852};
6853
6854TEST_F(ExternalStylusFusionTest, UsesBluetoothStylusSource) {
6855 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006856 ASSERT_EQ(STYLUS_FUSION_SOURCE, mapper.getSources());
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006857}
6858
6859TEST_F(ExternalStylusFusionTest, UnsuccessfulFusion) {
6860 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6861 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6862}
6863
6864TEST_F(ExternalStylusFusionTest, SuccessfulFusion_TouchFirst) {
6865 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6866 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6867}
6868
6869// Test a successful stylus fusion gesture where the pressure is reported by the external
6870// before the touch is reported by the touchscreen.
6871TEST_F(ExternalStylusFusionTest, SuccessfulFusion_PressureFirst) {
6872 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006873 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006874
6875 // The external stylus reports pressure first. It is ignored for now.
6876 mStylusState.pressure = 1.f;
6877 processExternalStylusState(mapper);
6878 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6879 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6880
6881 // When the touch goes down afterwards, it is reported as a stylus pointer.
6882 processDown(mapper, 100, 200);
6883 processSync(mapper);
6884 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6885 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6886 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6887
6888 processMove(mapper, 101, 201);
6889 processSync(mapper);
6890 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6891 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6892 processUp(mapper);
6893 processSync(mapper);
6894 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6895 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP))));
6896
6897 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6898 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6899}
6900
6901TEST_F(ExternalStylusFusionTest, FusionIsRepeatedForEachNewGesture) {
6902 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6903
6904 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6905 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6906
6907 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6908 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6909 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6910 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6911}
6912
6913TEST_F(ExternalStylusFusionTest, FusedPointerReportsPressureChanges) {
6914 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006915 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006916
6917 mStylusState.pressure = 0.8f;
6918 processExternalStylusState(mapper);
6919 processDown(mapper, 100, 200);
6920 processSync(mapper);
6921 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6922 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6923 WithPressure(0.8f))));
6924 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6925
6926 // The external stylus reports a pressure change. We wait for some time for a touch event.
6927 mStylusState.pressure = 0.6f;
6928 processExternalStylusState(mapper);
6929 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6930 ASSERT_NO_FATAL_FAILURE(
6931 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6932
6933 // If a touch is reported within the timeout, it reports the updated pressure.
6934 processMove(mapper, 101, 201);
6935 processSync(mapper);
6936 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6937 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6938 WithPressure(0.6f))));
6939 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6940
6941 // There is another pressure change.
6942 mStylusState.pressure = 0.5f;
6943 processExternalStylusState(mapper);
6944 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6945 ASSERT_NO_FATAL_FAILURE(
6946 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6947
6948 // If a touch is not reported within the timeout, a move event is generated to report
6949 // the new pressure.
6950 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
6951 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6952 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6953 WithPressure(0.5f))));
6954
6955 // If a zero pressure is reported before the touch goes up, the previous pressure value is
6956 // repeated indefinitely.
6957 mStylusState.pressure = 0.0f;
6958 processExternalStylusState(mapper);
6959 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6960 ASSERT_NO_FATAL_FAILURE(
6961 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6962 processMove(mapper, 102, 202);
6963 processSync(mapper);
6964 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6965 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6966 WithPressure(0.5f))));
6967 processMove(mapper, 103, 203);
6968 processSync(mapper);
6969 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6970 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6971 WithPressure(0.5f))));
6972
6973 processUp(mapper);
6974 processSync(mapper);
6975 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006976 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(STYLUS_FUSION_SOURCE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006977 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006978
6979 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6980 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6981}
6982
6983TEST_F(ExternalStylusFusionTest, FusedPointerReportsToolTypeChanges) {
6984 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006985 auto source = WithSource(STYLUS_FUSION_SOURCE);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006986
6987 mStylusState.pressure = 1.f;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006988 mStylusState.toolType = ToolType::ERASER;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006989 processExternalStylusState(mapper);
6990 processDown(mapper, 100, 200);
6991 processSync(mapper);
6992 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6993 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006994 WithToolType(ToolType::ERASER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006995 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6996
6997 // The external stylus reports a tool change. We wait for some time for a touch event.
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006998 mStylusState.toolType = ToolType::STYLUS;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006999 processExternalStylusState(mapper);
7000 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7001 ASSERT_NO_FATAL_FAILURE(
7002 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7003
7004 // If a touch is reported within the timeout, it reports the updated pressure.
7005 processMove(mapper, 101, 201);
7006 processSync(mapper);
7007 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7008 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007009 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007010 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7011
7012 // There is another tool type change.
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007013 mStylusState.toolType = ToolType::FINGER;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007014 processExternalStylusState(mapper);
7015 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7016 ASSERT_NO_FATAL_FAILURE(
7017 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7018
7019 // If a touch is not reported within the timeout, a move event is generated to report
7020 // the new tool type.
7021 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
7022 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7023 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007024 WithToolType(ToolType::FINGER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007025
7026 processUp(mapper);
7027 processSync(mapper);
7028 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7029 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007030 WithToolType(ToolType::FINGER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007031
7032 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7033 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7034}
7035
7036TEST_F(ExternalStylusFusionTest, FusedPointerReportsButtons) {
7037 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00007038 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007039
7040 ASSERT_NO_FATAL_FAILURE(testStartFusedStylusGesture(mapper));
7041
7042 // The external stylus reports a button change. We wait for some time for a touch event.
7043 mStylusState.buttons = AMOTION_EVENT_BUTTON_STYLUS_PRIMARY;
7044 processExternalStylusState(mapper);
7045 ASSERT_NO_FATAL_FAILURE(
7046 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7047
7048 // If a touch is reported within the timeout, it reports the updated button state.
7049 processMove(mapper, 101, 201);
7050 processSync(mapper);
7051 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7052 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
7053 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
7054 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7055 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
7056 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
7057 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7058
7059 // The button is now released.
7060 mStylusState.buttons = 0;
7061 processExternalStylusState(mapper);
7062 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7063 ASSERT_NO_FATAL_FAILURE(
7064 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7065
7066 // If a touch is not reported within the timeout, a move event is generated to report
7067 // the new button state.
7068 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007069 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7070 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
7071 WithButtonState(0))));
7072 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhan124ea442022-10-28 20:27:44 +00007073 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
7074 WithButtonState(0))));
7075
7076 processUp(mapper);
7077 processSync(mapper);
7078 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007079 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
7080
7081 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7082 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7083}
7084
Michael Wrightd02c5b62014-02-10 15:10:22 -08007085// --- MultiTouchInputMapperTest ---
7086
7087class MultiTouchInputMapperTest : public TouchInputMapperTest {
7088protected:
7089 void prepareAxes(int axes);
7090
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007091 void processPosition(MultiTouchInputMapper& mapper, int32_t x, int32_t y);
7092 void processTouchMajor(MultiTouchInputMapper& mapper, int32_t touchMajor);
7093 void processTouchMinor(MultiTouchInputMapper& mapper, int32_t touchMinor);
7094 void processToolMajor(MultiTouchInputMapper& mapper, int32_t toolMajor);
7095 void processToolMinor(MultiTouchInputMapper& mapper, int32_t toolMinor);
7096 void processOrientation(MultiTouchInputMapper& mapper, int32_t orientation);
7097 void processPressure(MultiTouchInputMapper& mapper, int32_t pressure);
7098 void processDistance(MultiTouchInputMapper& mapper, int32_t distance);
7099 void processId(MultiTouchInputMapper& mapper, int32_t id);
7100 void processSlot(MultiTouchInputMapper& mapper, int32_t slot);
7101 void processToolType(MultiTouchInputMapper& mapper, int32_t toolType);
7102 void processKey(MultiTouchInputMapper& mapper, int32_t code, int32_t value);
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00007103 void processHidUsage(MultiTouchInputMapper& mapper, int32_t usageCode, int32_t value);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007104 void processMTSync(MultiTouchInputMapper& mapper);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00007105 void processSync(MultiTouchInputMapper& mapper, nsecs_t eventTime = ARBITRARY_TIME,
7106 nsecs_t readTime = READ_TIME);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007107};
7108
7109void MultiTouchInputMapperTest::prepareAxes(int axes) {
7110 if (axes & POSITION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007111 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
7112 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007113 }
7114 if (axes & TOUCH) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007115 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN,
7116 RAW_TOUCH_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007117 if (axes & MINOR) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007118 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN,
7119 RAW_TOUCH_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007120 }
7121 }
7122 if (axes & TOOL) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007123 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7124 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007125 if (axes & MINOR) {
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007126 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MIN,
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007127 RAW_TOOL_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007128 }
7129 }
7130 if (axes & ORIENTATION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007131 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_ORIENTATION, RAW_ORIENTATION_MIN,
7132 RAW_ORIENTATION_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007133 }
7134 if (axes & PRESSURE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007135 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_PRESSURE, RAW_PRESSURE_MIN,
7136 RAW_PRESSURE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007137 }
7138 if (axes & DISTANCE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007139 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_DISTANCE, RAW_DISTANCE_MIN,
7140 RAW_DISTANCE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007141 }
7142 if (axes & ID) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007143 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TRACKING_ID, RAW_ID_MIN, RAW_ID_MAX, 0,
7144 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007145 }
7146 if (axes & SLOT) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007147 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_SLOT, RAW_SLOT_MIN, RAW_SLOT_MAX, 0, 0);
7148 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007149 }
7150 if (axes & TOOL_TYPE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007151 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007152 }
7153}
7154
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007155void MultiTouchInputMapperTest::processPosition(MultiTouchInputMapper& mapper, int32_t x,
7156 int32_t y) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007157 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
7158 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007159}
7160
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007161void MultiTouchInputMapperTest::processTouchMajor(MultiTouchInputMapper& mapper,
7162 int32_t touchMajor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007163 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOUCH_MAJOR, touchMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007164}
7165
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007166void MultiTouchInputMapperTest::processTouchMinor(MultiTouchInputMapper& mapper,
7167 int32_t touchMinor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007168 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOUCH_MINOR, touchMinor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007169}
7170
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007171void MultiTouchInputMapperTest::processToolMajor(MultiTouchInputMapper& mapper, int32_t toolMajor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007172 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_WIDTH_MAJOR, toolMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007173}
7174
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007175void MultiTouchInputMapperTest::processToolMinor(MultiTouchInputMapper& mapper, int32_t toolMinor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007176 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_WIDTH_MINOR, toolMinor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007177}
7178
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007179void MultiTouchInputMapperTest::processOrientation(MultiTouchInputMapper& mapper,
7180 int32_t orientation) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007181 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_ORIENTATION, orientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007182}
7183
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007184void MultiTouchInputMapperTest::processPressure(MultiTouchInputMapper& mapper, int32_t pressure) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007185 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_PRESSURE, pressure);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007186}
7187
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007188void MultiTouchInputMapperTest::processDistance(MultiTouchInputMapper& mapper, int32_t distance) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007189 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_DISTANCE, distance);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007190}
7191
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007192void MultiTouchInputMapperTest::processId(MultiTouchInputMapper& mapper, int32_t id) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007193 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TRACKING_ID, id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007194}
7195
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007196void MultiTouchInputMapperTest::processSlot(MultiTouchInputMapper& mapper, int32_t slot) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007197 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_SLOT, slot);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007198}
7199
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007200void MultiTouchInputMapperTest::processToolType(MultiTouchInputMapper& mapper, int32_t toolType) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007201 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOOL_TYPE, toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007202}
7203
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007204void MultiTouchInputMapperTest::processKey(MultiTouchInputMapper& mapper, int32_t code,
7205 int32_t value) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007206 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007207}
7208
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00007209void MultiTouchInputMapperTest::processHidUsage(MultiTouchInputMapper& mapper, int32_t usageCode,
7210 int32_t value) {
7211 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, usageCode);
7212 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, value);
7213}
7214
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007215void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper& mapper) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007216 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_MT_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007217}
7218
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00007219void MultiTouchInputMapperTest::processSync(MultiTouchInputMapper& mapper, nsecs_t eventTime,
7220 nsecs_t readTime) {
7221 process(mapper, eventTime, readTime, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007222}
7223
Michael Wrightd02c5b62014-02-10 15:10:22 -08007224TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackingIds) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007225 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007226 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007227 prepareAxes(POSITION);
7228 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007229 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007230
arthurhungdcef2dc2020-08-11 14:47:50 +08007231 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007232
7233 NotifyMotionArgs motionArgs;
7234
7235 // Two fingers down at once.
7236 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7237 processPosition(mapper, x1, y1);
7238 processMTSync(mapper);
7239 processPosition(mapper, x2, y2);
7240 processMTSync(mapper);
7241 processSync(mapper);
7242
7243 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7244 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7245 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7246 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7247 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7248 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
7249 ASSERT_EQ(0, motionArgs.flags);
7250 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7251 ASSERT_EQ(0, motionArgs.buttonState);
7252 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007253 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007254 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007255 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007256 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7257 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7258 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7259 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7260 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7261
7262 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7263 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7264 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7265 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7266 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007267 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007268 ASSERT_EQ(0, motionArgs.flags);
7269 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7270 ASSERT_EQ(0, motionArgs.buttonState);
7271 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007272 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007273 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007274 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007275 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007276 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007277 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7278 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7279 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7280 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7281 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7282 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7283 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7284
7285 // Move.
7286 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7287 processPosition(mapper, x1, y1);
7288 processMTSync(mapper);
7289 processPosition(mapper, x2, y2);
7290 processMTSync(mapper);
7291 processSync(mapper);
7292
7293 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7294 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7295 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7296 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7297 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7298 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7299 ASSERT_EQ(0, motionArgs.flags);
7300 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7301 ASSERT_EQ(0, motionArgs.buttonState);
7302 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007303 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007304 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007305 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007306 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007307 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007308 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7309 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7310 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7311 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7312 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7313 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7314 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7315
7316 // First finger up.
7317 x2 += 15; y2 -= 20;
7318 processPosition(mapper, x2, y2);
7319 processMTSync(mapper);
7320 processSync(mapper);
7321
7322 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7323 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7324 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7325 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7326 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007327 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007328 ASSERT_EQ(0, motionArgs.flags);
7329 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7330 ASSERT_EQ(0, motionArgs.buttonState);
7331 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007332 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007333 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007334 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007335 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007336 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007337 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7338 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7339 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7340 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7341 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7342 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7343 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7344
7345 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7346 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7347 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7348 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7349 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7350 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7351 ASSERT_EQ(0, motionArgs.flags);
7352 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7353 ASSERT_EQ(0, motionArgs.buttonState);
7354 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007355 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007356 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007357 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007358 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7359 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7360 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7361 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7362 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7363
7364 // Move.
7365 x2 += 20; y2 -= 25;
7366 processPosition(mapper, x2, y2);
7367 processMTSync(mapper);
7368 processSync(mapper);
7369
7370 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7371 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7372 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7373 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7374 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7375 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7376 ASSERT_EQ(0, motionArgs.flags);
7377 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7378 ASSERT_EQ(0, motionArgs.buttonState);
7379 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007380 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007381 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007382 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007383 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7384 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7385 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7386 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7387 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7388
7389 // New finger down.
7390 int32_t x3 = 700, y3 = 300;
7391 processPosition(mapper, x2, y2);
7392 processMTSync(mapper);
7393 processPosition(mapper, x3, y3);
7394 processMTSync(mapper);
7395 processSync(mapper);
7396
7397 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7398 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7399 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7400 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7401 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007402 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007403 ASSERT_EQ(0, motionArgs.flags);
7404 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7405 ASSERT_EQ(0, motionArgs.buttonState);
7406 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007407 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007408 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007409 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007410 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007411 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007412 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7413 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7414 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7415 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7416 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7417 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7418 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7419
7420 // Second finger up.
7421 x3 += 30; y3 -= 20;
7422 processPosition(mapper, x3, y3);
7423 processMTSync(mapper);
7424 processSync(mapper);
7425
7426 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7427 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7428 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7429 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7430 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007431 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007432 ASSERT_EQ(0, motionArgs.flags);
7433 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7434 ASSERT_EQ(0, motionArgs.buttonState);
7435 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007436 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007437 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007438 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007439 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007440 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007441 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7442 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7443 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7444 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7445 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7446 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7447 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7448
7449 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7450 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7451 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7452 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7453 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7454 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7455 ASSERT_EQ(0, motionArgs.flags);
7456 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7457 ASSERT_EQ(0, motionArgs.buttonState);
7458 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007459 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007460 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007461 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007462 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7463 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7464 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7465 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7466 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7467
7468 // Last finger up.
7469 processMTSync(mapper);
7470 processSync(mapper);
7471
7472 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7473 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7474 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7475 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7476 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7477 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
7478 ASSERT_EQ(0, motionArgs.flags);
7479 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7480 ASSERT_EQ(0, motionArgs.buttonState);
7481 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007482 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007483 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007484 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007485 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7486 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7487 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7488 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7489 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7490
7491 // Should not have sent any more keys or motions.
7492 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7493 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7494}
7495
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007496TEST_F(MultiTouchInputMapperTest, AxisResolution_IsPopulated) {
7497 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007498 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007499
7500 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, /*flat*/ 0,
7501 /*fuzz*/ 0, /*resolution*/ 10);
7502 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, /*flat*/ 0,
7503 /*fuzz*/ 0, /*resolution*/ 11);
7504 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX,
7505 /*flat*/ 0, /*fuzz*/ 0, /*resolution*/ 12);
7506 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX,
7507 /*flat*/ 0, /*fuzz*/ 0, /*resolution*/ 13);
7508 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7509 /*flat*/ 0, /*flat*/ 0, /*resolution*/ 14);
7510 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7511 /*flat*/ 0, /*flat*/ 0, /*resolution*/ 15);
7512
Arpit Singha8c236b2023-04-25 13:56:05 +00007513 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007514
7515 // X and Y axes
7516 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_X, 10 / X_PRECISION);
7517 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_Y, 11 / Y_PRECISION);
7518 // Touch major and minor
7519 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOUCH_MAJOR, 12 * GEOMETRIC_SCALE);
7520 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOUCH_MINOR, 13 * GEOMETRIC_SCALE);
7521 // Tool major and minor
7522 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOOL_MAJOR, 14 * GEOMETRIC_SCALE);
7523 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOOL_MINOR, 15 * GEOMETRIC_SCALE);
7524}
7525
7526TEST_F(MultiTouchInputMapperTest, TouchMajorAndMinorAxes_DoNotAppearIfNotSupported) {
7527 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007528 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007529
7530 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, /*flat*/ 0,
7531 /*fuzz*/ 0, /*resolution*/ 10);
7532 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, /*flat*/ 0,
7533 /*fuzz*/ 0, /*resolution*/ 11);
7534
7535 // We do not add ABS_MT_TOUCH_MAJOR / MINOR or ABS_MT_WIDTH_MAJOR / MINOR axes
7536
Arpit Singha8c236b2023-04-25 13:56:05 +00007537 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007538
7539 // Touch major and minor
7540 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOUCH_MAJOR);
7541 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOUCH_MINOR);
7542 // Tool major and minor
7543 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOOL_MAJOR);
7544 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOOL_MINOR);
7545}
7546
Michael Wrightd02c5b62014-02-10 15:10:22 -08007547TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingIds) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007548 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007549 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007550 prepareAxes(POSITION | ID);
7551 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007552 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007553
arthurhungdcef2dc2020-08-11 14:47:50 +08007554 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007555
7556 NotifyMotionArgs motionArgs;
7557
7558 // Two fingers down at once.
7559 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7560 processPosition(mapper, x1, y1);
7561 processId(mapper, 1);
7562 processMTSync(mapper);
7563 processPosition(mapper, x2, y2);
7564 processId(mapper, 2);
7565 processMTSync(mapper);
7566 processSync(mapper);
7567
7568 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7569 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007570 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007571 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007572 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007573 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7574 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7575
7576 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007577 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007578 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007579 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007580 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007581 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007582 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007583 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7584 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7585 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7586 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7587
7588 // Move.
7589 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7590 processPosition(mapper, x1, y1);
7591 processId(mapper, 1);
7592 processMTSync(mapper);
7593 processPosition(mapper, x2, y2);
7594 processId(mapper, 2);
7595 processMTSync(mapper);
7596 processSync(mapper);
7597
7598 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7599 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007600 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007601 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007602 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007603 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007604 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007605 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7606 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7607 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7608 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7609
7610 // First finger up.
7611 x2 += 15; y2 -= 20;
7612 processPosition(mapper, x2, y2);
7613 processId(mapper, 2);
7614 processMTSync(mapper);
7615 processSync(mapper);
7616
7617 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007618 ASSERT_EQ(ACTION_POINTER_0_UP, 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 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7630 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007631 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007632 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007633 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007634 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7635 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7636
7637 // Move.
7638 x2 += 20; y2 -= 25;
7639 processPosition(mapper, x2, y2);
7640 processId(mapper, 2);
7641 processMTSync(mapper);
7642 processSync(mapper);
7643
7644 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7645 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007646 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007647 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007648 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007649 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7650 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7651
7652 // New finger down.
7653 int32_t x3 = 700, y3 = 300;
7654 processPosition(mapper, x2, y2);
7655 processId(mapper, 2);
7656 processMTSync(mapper);
7657 processPosition(mapper, x3, y3);
7658 processId(mapper, 3);
7659 processMTSync(mapper);
7660 processSync(mapper);
7661
7662 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007663 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007664 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007665 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007666 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007667 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007668 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007669 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7670 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7671 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7672 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7673
7674 // Second finger up.
7675 x3 += 30; y3 -= 20;
7676 processPosition(mapper, x3, y3);
7677 processId(mapper, 3);
7678 processMTSync(mapper);
7679 processSync(mapper);
7680
7681 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007682 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007683 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007684 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007685 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007686 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007687 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007688 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7689 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7690 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7691 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7692
7693 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7694 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007695 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007696 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007697 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007698 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7699 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7700
7701 // Last finger up.
7702 processMTSync(mapper);
7703 processSync(mapper);
7704
7705 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7706 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007707 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007708 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007709 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].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
7713 // Should not have sent any more keys or motions.
7714 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7715 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7716}
7717
7718TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithSlots) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007719 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007720 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007721 prepareAxes(POSITION | ID | SLOT);
7722 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007723 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007724
arthurhungdcef2dc2020-08-11 14:47:50 +08007725 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007726
7727 NotifyMotionArgs motionArgs;
7728
7729 // Two fingers down at once.
7730 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7731 processPosition(mapper, x1, y1);
7732 processId(mapper, 1);
7733 processSlot(mapper, 1);
7734 processPosition(mapper, x2, y2);
7735 processId(mapper, 2);
7736 processSync(mapper);
7737
7738 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7739 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007740 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007741 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007742 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007743 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7744 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7745
7746 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007747 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007748 ASSERT_EQ(size_t(2), 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_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007752 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007753 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7754 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7755 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7756 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7757
7758 // Move.
7759 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7760 processSlot(mapper, 0);
7761 processPosition(mapper, x1, y1);
7762 processSlot(mapper, 1);
7763 processPosition(mapper, x2, y2);
7764 processSync(mapper);
7765
7766 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7767 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007768 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007769 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007770 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007771 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007772 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007773 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7774 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7775 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7776 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7777
7778 // First finger up.
7779 x2 += 15; y2 -= 20;
7780 processSlot(mapper, 0);
7781 processId(mapper, -1);
7782 processSlot(mapper, 1);
7783 processPosition(mapper, x2, y2);
7784 processSync(mapper);
7785
7786 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007787 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007788 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007789 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007790 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007791 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007792 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007793 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7794 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7795 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7796 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7797
7798 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7799 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007800 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007801 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007802 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007803 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7804 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7805
7806 // Move.
7807 x2 += 20; y2 -= 25;
7808 processPosition(mapper, x2, y2);
7809 processSync(mapper);
7810
7811 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7812 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007813 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007814 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007815 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007816 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7817 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7818
7819 // New finger down.
7820 int32_t x3 = 700, y3 = 300;
7821 processPosition(mapper, x2, y2);
7822 processSlot(mapper, 0);
7823 processId(mapper, 3);
7824 processPosition(mapper, x3, y3);
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_DOWN, 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(x3), toDisplayY(y3), 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 // Second finger up.
7840 x3 += 30; y3 -= 20;
7841 processSlot(mapper, 1);
7842 processId(mapper, -1);
7843 processSlot(mapper, 0);
7844 processPosition(mapper, x3, y3);
7845 processSync(mapper);
7846
7847 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007848 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007849 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007850 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007851 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007852 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007853 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007854 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7855 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7856 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7857 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7858
7859 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7860 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007861 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007862 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007863 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007864 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7865 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7866
7867 // Last finger up.
7868 processId(mapper, -1);
7869 processSync(mapper);
7870
7871 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7872 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007873 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007874 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007875 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007876 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7877 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7878
7879 // Should not have sent any more keys or motions.
7880 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7881 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7882}
7883
7884TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007885 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007886 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007887 prepareAxes(POSITION | TOUCH | TOOL | PRESSURE | ORIENTATION | ID | MINOR | DISTANCE);
Arpit Singha8c236b2023-04-25 13:56:05 +00007888 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007889
7890 // These calculations are based on the input device calibration documentation.
7891 int32_t rawX = 100;
7892 int32_t rawY = 200;
7893 int32_t rawTouchMajor = 7;
7894 int32_t rawTouchMinor = 6;
7895 int32_t rawToolMajor = 9;
7896 int32_t rawToolMinor = 8;
7897 int32_t rawPressure = 11;
7898 int32_t rawDistance = 0;
7899 int32_t rawOrientation = 3;
7900 int32_t id = 5;
7901
7902 float x = toDisplayX(rawX);
7903 float y = toDisplayY(rawY);
7904 float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
7905 float size = avg(rawTouchMajor, rawTouchMinor) / RAW_TOUCH_MAX;
7906 float toolMajor = float(rawToolMajor) * GEOMETRIC_SCALE;
7907 float toolMinor = float(rawToolMinor) * GEOMETRIC_SCALE;
7908 float touchMajor = float(rawTouchMajor) * GEOMETRIC_SCALE;
7909 float touchMinor = float(rawTouchMinor) * GEOMETRIC_SCALE;
7910 float orientation = float(rawOrientation) / RAW_ORIENTATION_MAX * M_PI_2;
7911 float distance = float(rawDistance);
7912
7913 processPosition(mapper, rawX, rawY);
7914 processTouchMajor(mapper, rawTouchMajor);
7915 processTouchMinor(mapper, rawTouchMinor);
7916 processToolMajor(mapper, rawToolMajor);
7917 processToolMinor(mapper, rawToolMinor);
7918 processPressure(mapper, rawPressure);
7919 processOrientation(mapper, rawOrientation);
7920 processDistance(mapper, rawDistance);
7921 processId(mapper, id);
7922 processMTSync(mapper);
7923 processSync(mapper);
7924
7925 NotifyMotionArgs args;
7926 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7927 ASSERT_EQ(0, args.pointerProperties[0].id);
7928 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7929 x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor,
7930 orientation, distance));
7931}
7932
7933TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_GeometricCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007934 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007935 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007936 prepareAxes(POSITION | TOUCH | TOOL | MINOR);
7937 addConfigurationProperty("touch.size.calibration", "geometric");
Arpit Singha8c236b2023-04-25 13:56:05 +00007938 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007939
7940 // These calculations are based on the input device calibration documentation.
7941 int32_t rawX = 100;
7942 int32_t rawY = 200;
7943 int32_t rawTouchMajor = 140;
7944 int32_t rawTouchMinor = 120;
7945 int32_t rawToolMajor = 180;
7946 int32_t rawToolMinor = 160;
7947
7948 float x = toDisplayX(rawX);
7949 float y = toDisplayY(rawY);
7950 float size = avg(rawTouchMajor, rawTouchMinor) / RAW_TOUCH_MAX;
7951 float toolMajor = float(rawToolMajor) * GEOMETRIC_SCALE;
7952 float toolMinor = float(rawToolMinor) * GEOMETRIC_SCALE;
7953 float touchMajor = float(rawTouchMajor) * GEOMETRIC_SCALE;
7954 float touchMinor = float(rawTouchMinor) * GEOMETRIC_SCALE;
7955
7956 processPosition(mapper, rawX, rawY);
7957 processTouchMajor(mapper, rawTouchMajor);
7958 processTouchMinor(mapper, rawTouchMinor);
7959 processToolMajor(mapper, rawToolMajor);
7960 processToolMinor(mapper, rawToolMinor);
7961 processMTSync(mapper);
7962 processSync(mapper);
7963
7964 NotifyMotionArgs args;
7965 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7966 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7967 x, y, 1.0f, size, touchMajor, touchMinor, toolMajor, toolMinor, 0, 0));
7968}
7969
7970TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_SummedLinearCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007971 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007972 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007973 prepareAxes(POSITION | TOUCH | TOOL);
7974 addConfigurationProperty("touch.size.calibration", "diameter");
7975 addConfigurationProperty("touch.size.scale", "10");
7976 addConfigurationProperty("touch.size.bias", "160");
7977 addConfigurationProperty("touch.size.isSummed", "1");
Arpit Singha8c236b2023-04-25 13:56:05 +00007978 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007979
7980 // These calculations are based on the input device calibration documentation.
7981 // Note: We only provide a single common touch/tool value because the device is assumed
7982 // not to emit separate values for each pointer (isSummed = 1).
7983 int32_t rawX = 100;
7984 int32_t rawY = 200;
7985 int32_t rawX2 = 150;
7986 int32_t rawY2 = 250;
7987 int32_t rawTouchMajor = 5;
7988 int32_t rawToolMajor = 8;
7989
7990 float x = toDisplayX(rawX);
7991 float y = toDisplayY(rawY);
7992 float x2 = toDisplayX(rawX2);
7993 float y2 = toDisplayY(rawY2);
7994 float size = float(rawTouchMajor) / 2 / RAW_TOUCH_MAX;
7995 float touch = float(rawTouchMajor) / 2 * 10.0f + 160.0f;
7996 float tool = float(rawToolMajor) / 2 * 10.0f + 160.0f;
7997
7998 processPosition(mapper, rawX, rawY);
7999 processTouchMajor(mapper, rawTouchMajor);
8000 processToolMajor(mapper, rawToolMajor);
8001 processMTSync(mapper);
8002 processPosition(mapper, rawX2, rawY2);
8003 processTouchMajor(mapper, rawTouchMajor);
8004 processToolMajor(mapper, rawToolMajor);
8005 processMTSync(mapper);
8006 processSync(mapper);
8007
8008 NotifyMotionArgs args;
8009 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8010 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
8011
8012 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08008013 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07008014 ASSERT_EQ(size_t(2), args.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08008015 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8016 x, y, 1.0f, size, touch, touch, tool, tool, 0, 0));
8017 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[1],
8018 x2, y2, 1.0f, size, touch, touch, tool, tool, 0, 0));
8019}
8020
8021TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_AreaCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008022 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008023 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008024 prepareAxes(POSITION | TOUCH | TOOL);
8025 addConfigurationProperty("touch.size.calibration", "area");
8026 addConfigurationProperty("touch.size.scale", "43");
8027 addConfigurationProperty("touch.size.bias", "3");
Arpit Singha8c236b2023-04-25 13:56:05 +00008028 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008029
8030 // These calculations are based on the input device calibration documentation.
8031 int32_t rawX = 100;
8032 int32_t rawY = 200;
8033 int32_t rawTouchMajor = 5;
8034 int32_t rawToolMajor = 8;
8035
8036 float x = toDisplayX(rawX);
8037 float y = toDisplayY(rawY);
8038 float size = float(rawTouchMajor) / RAW_TOUCH_MAX;
8039 float touch = sqrtf(rawTouchMajor) * 43.0f + 3.0f;
8040 float tool = sqrtf(rawToolMajor) * 43.0f + 3.0f;
8041
8042 processPosition(mapper, rawX, rawY);
8043 processTouchMajor(mapper, rawTouchMajor);
8044 processToolMajor(mapper, rawToolMajor);
8045 processMTSync(mapper);
8046 processSync(mapper);
8047
8048 NotifyMotionArgs args;
8049 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8050 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8051 x, y, 1.0f, size, touch, touch, tool, tool, 0, 0));
8052}
8053
8054TEST_F(MultiTouchInputMapperTest, Process_PressureAxis_AmplitudeCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008055 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008056 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008057 prepareAxes(POSITION | PRESSURE);
8058 addConfigurationProperty("touch.pressure.calibration", "amplitude");
8059 addConfigurationProperty("touch.pressure.scale", "0.01");
Arpit Singha8c236b2023-04-25 13:56:05 +00008060 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008061
Michael Wrightaa449c92017-12-13 21:21:43 +00008062 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +00008063 mapper.populateDeviceInfo(info);
Michael Wrightaa449c92017-12-13 21:21:43 +00008064 ASSERT_NO_FATAL_FAILURE(assertMotionRange(info,
8065 AINPUT_MOTION_RANGE_PRESSURE, AINPUT_SOURCE_TOUCHSCREEN,
8066 0.0f, RAW_PRESSURE_MAX * 0.01, 0.0f, 0.0f));
8067
Michael Wrightd02c5b62014-02-10 15:10:22 -08008068 // These calculations are based on the input device calibration documentation.
8069 int32_t rawX = 100;
8070 int32_t rawY = 200;
8071 int32_t rawPressure = 60;
8072
8073 float x = toDisplayX(rawX);
8074 float y = toDisplayY(rawY);
8075 float pressure = float(rawPressure) * 0.01f;
8076
8077 processPosition(mapper, rawX, rawY);
8078 processPressure(mapper, rawPressure);
8079 processMTSync(mapper);
8080 processSync(mapper);
8081
8082 NotifyMotionArgs args;
8083 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8084 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8085 x, y, pressure, 0, 0, 0, 0, 0, 0, 0));
8086}
8087
8088TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllButtons) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008089 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008090 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008091 prepareAxes(POSITION | ID | SLOT);
Arpit Singha8c236b2023-04-25 13:56:05 +00008092 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008093
8094 NotifyMotionArgs motionArgs;
8095 NotifyKeyArgs keyArgs;
8096
8097 processId(mapper, 1);
8098 processPosition(mapper, 100, 200);
8099 processSync(mapper);
8100 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8101 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8102 ASSERT_EQ(0, motionArgs.buttonState);
8103
8104 // press BTN_LEFT, release BTN_LEFT
8105 processKey(mapper, BTN_LEFT, 1);
8106 processSync(mapper);
8107 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8108 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
8109 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
8110
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008111 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8112 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8113 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
8114
Michael Wrightd02c5b62014-02-10 15:10:22 -08008115 processKey(mapper, BTN_LEFT, 0);
8116 processSync(mapper);
8117 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008118 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008119 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008120
8121 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008122 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008123 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008124
8125 // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
8126 processKey(mapper, BTN_RIGHT, 1);
8127 processKey(mapper, BTN_MIDDLE, 1);
8128 processSync(mapper);
8129 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8130 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
8131 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
8132 motionArgs.buttonState);
8133
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008134 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8135 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8136 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
8137
8138 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8139 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8140 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
8141 motionArgs.buttonState);
8142
Michael Wrightd02c5b62014-02-10 15:10:22 -08008143 processKey(mapper, BTN_RIGHT, 0);
8144 processSync(mapper);
8145 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008146 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008147 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008148
8149 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008150 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008151 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008152
8153 processKey(mapper, BTN_MIDDLE, 0);
8154 processSync(mapper);
8155 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008156 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008157 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008158
8159 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008160 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008161 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008162
8163 // press BTN_BACK, release BTN_BACK
8164 processKey(mapper, BTN_BACK, 1);
8165 processSync(mapper);
8166 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8167 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8168 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008169
Michael Wrightd02c5b62014-02-10 15:10:22 -08008170 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008171 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008172 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
8173
8174 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8175 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8176 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008177
8178 processKey(mapper, BTN_BACK, 0);
8179 processSync(mapper);
8180 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008181 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008182 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008183
8184 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008185 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008186 ASSERT_EQ(0, motionArgs.buttonState);
8187
Michael Wrightd02c5b62014-02-10 15:10:22 -08008188 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8189 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8190 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
8191
8192 // press BTN_SIDE, release BTN_SIDE
8193 processKey(mapper, BTN_SIDE, 1);
8194 processSync(mapper);
8195 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8196 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8197 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008198
Michael Wrightd02c5b62014-02-10 15:10:22 -08008199 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008200 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008201 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
8202
8203 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8204 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8205 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008206
8207 processKey(mapper, BTN_SIDE, 0);
8208 processSync(mapper);
8209 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008210 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008211 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008212
8213 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008214 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008215 ASSERT_EQ(0, motionArgs.buttonState);
8216
Michael Wrightd02c5b62014-02-10 15:10:22 -08008217 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8218 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8219 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
8220
8221 // press BTN_FORWARD, release BTN_FORWARD
8222 processKey(mapper, BTN_FORWARD, 1);
8223 processSync(mapper);
8224 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8225 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8226 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008227
Michael Wrightd02c5b62014-02-10 15:10:22 -08008228 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008229 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008230 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
8231
8232 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8233 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8234 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008235
8236 processKey(mapper, BTN_FORWARD, 0);
8237 processSync(mapper);
8238 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008239 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008240 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008241
8242 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008243 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008244 ASSERT_EQ(0, motionArgs.buttonState);
8245
Michael Wrightd02c5b62014-02-10 15:10:22 -08008246 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8247 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8248 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
8249
8250 // press BTN_EXTRA, release BTN_EXTRA
8251 processKey(mapper, BTN_EXTRA, 1);
8252 processSync(mapper);
8253 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8254 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8255 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008256
Michael Wrightd02c5b62014-02-10 15:10:22 -08008257 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008258 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008259 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
8260
8261 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8262 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8263 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008264
8265 processKey(mapper, BTN_EXTRA, 0);
8266 processSync(mapper);
8267 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008268 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008269 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008270
8271 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008272 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008273 ASSERT_EQ(0, motionArgs.buttonState);
8274
Michael Wrightd02c5b62014-02-10 15:10:22 -08008275 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8276 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8277 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
8278
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008279 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
8280
Michael Wrightd02c5b62014-02-10 15:10:22 -08008281 // press BTN_STYLUS, release BTN_STYLUS
8282 processKey(mapper, BTN_STYLUS, 1);
8283 processSync(mapper);
8284 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8285 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008286 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
8287
8288 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8289 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8290 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008291
8292 processKey(mapper, BTN_STYLUS, 0);
8293 processSync(mapper);
8294 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008295 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008296 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008297
8298 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008299 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008300 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008301
8302 // press BTN_STYLUS2, release BTN_STYLUS2
8303 processKey(mapper, BTN_STYLUS2, 1);
8304 processSync(mapper);
8305 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8306 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008307 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
8308
8309 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8310 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8311 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008312
8313 processKey(mapper, BTN_STYLUS2, 0);
8314 processSync(mapper);
8315 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008316 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008317 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008318
8319 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008320 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008321 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008322
8323 // release touch
8324 processId(mapper, -1);
8325 processSync(mapper);
8326 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8327 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8328 ASSERT_EQ(0, motionArgs.buttonState);
8329}
8330
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008331TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleMappedStylusButtons) {
8332 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008333 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008334 prepareAxes(POSITION | ID | SLOT);
Arpit Singha8c236b2023-04-25 13:56:05 +00008335 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008336
8337 mFakeEventHub->addKey(EVENTHUB_ID, BTN_A, 0, AKEYCODE_STYLUS_BUTTON_PRIMARY, 0);
8338 mFakeEventHub->addKey(EVENTHUB_ID, 0, 0xabcd, AKEYCODE_STYLUS_BUTTON_SECONDARY, 0);
8339
8340 // Touch down.
8341 processId(mapper, 1);
8342 processPosition(mapper, 100, 200);
8343 processSync(mapper);
8344 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8345 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithButtonState(0))));
8346
8347 // Press and release button mapped to the primary stylus button.
8348 processKey(mapper, BTN_A, 1);
8349 processSync(mapper);
8350 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8351 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
8352 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
8353 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8354 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
8355 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
8356
8357 processKey(mapper, BTN_A, 0);
8358 processSync(mapper);
8359 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8360 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithButtonState(0))));
8361 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8362 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
8363
8364 // Press and release the HID usage mapped to the secondary stylus button.
8365 processHidUsage(mapper, 0xabcd, 1);
8366 processSync(mapper);
8367 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8368 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
8369 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY))));
8370 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8371 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
8372 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY))));
8373
8374 processHidUsage(mapper, 0xabcd, 0);
8375 processSync(mapper);
8376 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8377 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithButtonState(0))));
8378 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8379 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
8380
8381 // Release touch.
8382 processId(mapper, -1);
8383 processSync(mapper);
8384 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8385 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
8386}
8387
Michael Wrightd02c5b62014-02-10 15:10:22 -08008388TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008389 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008390 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008391 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00008392 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008393
8394 NotifyMotionArgs motionArgs;
8395
8396 // default tool type is finger
8397 processId(mapper, 1);
8398 processPosition(mapper, 100, 200);
8399 processSync(mapper);
8400 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8401 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008402 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008403
8404 // eraser
8405 processKey(mapper, BTN_TOOL_RUBBER, 1);
8406 processSync(mapper);
8407 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8408 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008409 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008410
8411 // stylus
8412 processKey(mapper, BTN_TOOL_RUBBER, 0);
8413 processKey(mapper, BTN_TOOL_PEN, 1);
8414 processSync(mapper);
8415 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8416 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008417 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008418
8419 // brush
8420 processKey(mapper, BTN_TOOL_PEN, 0);
8421 processKey(mapper, BTN_TOOL_BRUSH, 1);
8422 processSync(mapper);
8423 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8424 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008425 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008426
8427 // pencil
8428 processKey(mapper, BTN_TOOL_BRUSH, 0);
8429 processKey(mapper, BTN_TOOL_PENCIL, 1);
8430 processSync(mapper);
8431 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8432 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008433 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008434
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08008435 // air-brush
Michael Wrightd02c5b62014-02-10 15:10:22 -08008436 processKey(mapper, BTN_TOOL_PENCIL, 0);
8437 processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
8438 processSync(mapper);
8439 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8440 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008441 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008442
8443 // mouse
8444 processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
8445 processKey(mapper, BTN_TOOL_MOUSE, 1);
8446 processSync(mapper);
8447 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8448 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008449 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008450
8451 // lens
8452 processKey(mapper, BTN_TOOL_MOUSE, 0);
8453 processKey(mapper, BTN_TOOL_LENS, 1);
8454 processSync(mapper);
8455 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8456 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008457 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008458
8459 // double-tap
8460 processKey(mapper, BTN_TOOL_LENS, 0);
8461 processKey(mapper, BTN_TOOL_DOUBLETAP, 1);
8462 processSync(mapper);
8463 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8464 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008465 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008466
8467 // triple-tap
8468 processKey(mapper, BTN_TOOL_DOUBLETAP, 0);
8469 processKey(mapper, BTN_TOOL_TRIPLETAP, 1);
8470 processSync(mapper);
8471 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8472 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008473 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008474
8475 // quad-tap
8476 processKey(mapper, BTN_TOOL_TRIPLETAP, 0);
8477 processKey(mapper, BTN_TOOL_QUADTAP, 1);
8478 processSync(mapper);
8479 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8480 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008481 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008482
8483 // finger
8484 processKey(mapper, BTN_TOOL_QUADTAP, 0);
8485 processKey(mapper, BTN_TOOL_FINGER, 1);
8486 processSync(mapper);
8487 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8488 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008489 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008490
8491 // stylus trumps finger
8492 processKey(mapper, BTN_TOOL_PEN, 1);
8493 processSync(mapper);
8494 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8495 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008496 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008497
8498 // eraser trumps stylus
8499 processKey(mapper, BTN_TOOL_RUBBER, 1);
8500 processSync(mapper);
8501 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8502 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008503 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008504
8505 // mouse trumps eraser
8506 processKey(mapper, BTN_TOOL_MOUSE, 1);
8507 processSync(mapper);
8508 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8509 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008510 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008511
8512 // MT tool type trumps BTN tool types: MT_TOOL_FINGER
8513 processToolType(mapper, MT_TOOL_FINGER); // this is the first time we send MT_TOOL_TYPE
8514 processSync(mapper);
8515 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8516 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008517 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008518
8519 // MT tool type trumps BTN tool types: MT_TOOL_PEN
8520 processToolType(mapper, MT_TOOL_PEN);
8521 processSync(mapper);
8522 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8523 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008524 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008525
8526 // back to default tool type
8527 processToolType(mapper, -1); // use a deliberately undefined tool type, for testing
8528 processKey(mapper, BTN_TOOL_MOUSE, 0);
8529 processKey(mapper, BTN_TOOL_RUBBER, 0);
8530 processKey(mapper, BTN_TOOL_PEN, 0);
8531 processKey(mapper, BTN_TOOL_FINGER, 0);
8532 processSync(mapper);
8533 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8534 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008535 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008536}
8537
8538TEST_F(MultiTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008539 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008540 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008541 prepareAxes(POSITION | ID | SLOT);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008542 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00008543 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008544
8545 NotifyMotionArgs motionArgs;
8546
8547 // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0
8548 processId(mapper, 1);
8549 processPosition(mapper, 100, 200);
8550 processSync(mapper);
8551 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8552 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8553 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8554 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8555
8556 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8557 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8558 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8559 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8560
8561 // move a little
8562 processPosition(mapper, 150, 250);
8563 processSync(mapper);
8564 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8565 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8566 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8567 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8568
8569 // down when BTN_TOUCH is pressed, pressure defaults to 1
8570 processKey(mapper, BTN_TOUCH, 1);
8571 processSync(mapper);
8572 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8573 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8574 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8575 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8576
8577 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8578 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8579 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8580 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8581
8582 // up when BTN_TOUCH is released, hover restored
8583 processKey(mapper, BTN_TOUCH, 0);
8584 processSync(mapper);
8585 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8586 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8587 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8588 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8589
8590 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8591 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8592 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8593 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8594
8595 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8596 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8597 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8598 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8599
8600 // exit hover when pointer goes away
8601 processId(mapper, -1);
8602 processSync(mapper);
8603 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8604 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8605 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8606 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8607}
8608
8609TEST_F(MultiTouchInputMapperTest, Process_WhenAbsMTPressureIsPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008610 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008611 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008612 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00008613 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008614
8615 NotifyMotionArgs motionArgs;
8616
8617 // initially hovering because pressure is 0
8618 processId(mapper, 1);
8619 processPosition(mapper, 100, 200);
8620 processPressure(mapper, 0);
8621 processSync(mapper);
8622 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8623 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8624 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8625 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8626
8627 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8628 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8629 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8630 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8631
8632 // move a little
8633 processPosition(mapper, 150, 250);
8634 processSync(mapper);
8635 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8636 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8637 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8638 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8639
8640 // down when pressure becomes non-zero
8641 processPressure(mapper, RAW_PRESSURE_MAX);
8642 processSync(mapper);
8643 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8644 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8645 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8646 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8647
8648 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8649 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8650 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8651 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8652
8653 // up when pressure becomes 0, hover restored
8654 processPressure(mapper, 0);
8655 processSync(mapper);
8656 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8657 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8658 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8659 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8660
8661 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8662 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8663 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8664 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8665
8666 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8667 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8668 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8669 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8670
8671 // exit hover when pointer goes away
8672 processId(mapper, -1);
8673 processSync(mapper);
8674 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8675 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8676 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8677 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8678}
8679
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008680/**
8681 * Set the input device port <--> display port associations, and check that the
8682 * events are routed to the display that matches the display port.
8683 * This can be checked by looking at the displayId of the resulting NotifyMotionArgs.
8684 */
8685TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayPort) {
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008686 const std::string usb2 = "USB2";
8687 const uint8_t hdmi1 = 0;
8688 const uint8_t hdmi2 = 1;
8689 const std::string secondaryUniqueId = "uniqueId2";
Michael Wrightfe3de7d2020-07-02 19:05:30 +01008690 constexpr ViewportType type = ViewportType::EXTERNAL;
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008691
8692 addConfigurationProperty("touch.deviceType", "touchScreen");
8693 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008694 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008695
8696 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
8697 mFakePolicy->addInputPortAssociation(usb2, hdmi2);
8698
8699 // We are intentionally not adding the viewport for display 1 yet. Since the port association
8700 // for this input device is specified, and the matching viewport is not present,
8701 // the input device should be disabled (at the mapper level).
8702
8703 // Add viewport for display 2 on hdmi2
8704 prepareSecondaryDisplay(type, hdmi2);
8705 // Send a touch event
8706 processPosition(mapper, 100, 100);
8707 processSync(mapper);
8708 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
8709
8710 // Add viewport for display 1 on hdmi1
Michael Wrighta9cf4192022-12-01 23:46:39 +00008711 prepareDisplay(ui::ROTATION_0, hdmi1);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008712 // Send a touch event again
8713 processPosition(mapper, 100, 100);
8714 processSync(mapper);
8715
8716 NotifyMotionArgs args;
8717 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8718 ASSERT_EQ(DISPLAY_ID, args.displayId);
8719}
Michael Wrightd02c5b62014-02-10 15:10:22 -08008720
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008721TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayUniqueId) {
8722 addConfigurationProperty("touch.deviceType", "touchScreen");
8723 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008724 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008725
8726 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID);
8727
Michael Wrighta9cf4192022-12-01 23:46:39 +00008728 prepareDisplay(ui::ROTATION_0);
8729 prepareVirtualDisplay(ui::ROTATION_0);
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008730
8731 // Send a touch event
8732 processPosition(mapper, 100, 100);
8733 processSync(mapper);
8734
8735 NotifyMotionArgs args;
8736 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8737 ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId);
8738}
8739
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008740TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01008741 prepareSecondaryDisplay(ViewportType::EXTERNAL);
Garfield Tan888a6a42020-01-09 11:39:16 -08008742
Michael Wrighta9cf4192022-12-01 23:46:39 +00008743 prepareDisplay(ui::ROTATION_0);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008744 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008745 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008746
Josep del Río2d8c79a2023-01-23 19:33:50 +00008747 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008748
8749 NotifyMotionArgs motionArgs;
8750 processPosition(mapper, 100, 100);
8751 processSync(mapper);
8752
8753 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8754 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
Linnan Li13bf76a2024-05-05 19:18:02 +08008755 ASSERT_EQ(ui::ADISPLAY_ID_NONE, motionArgs.displayId);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008756}
8757
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008758/**
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008759 * Ensure that the readTime is set to the SYN_REPORT value when processing touch events.
8760 */
8761TEST_F(MultiTouchInputMapperTest, Process_SendsReadTime) {
8762 addConfigurationProperty("touch.deviceType", "touchScreen");
8763 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008764 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008765
Michael Wrighta9cf4192022-12-01 23:46:39 +00008766 prepareDisplay(ui::ROTATION_0);
Harry Cutts33476232023-01-30 19:57:29 +00008767 process(mapper, 10, /*readTime=*/11, EV_ABS, ABS_MT_TRACKING_ID, 1);
8768 process(mapper, 15, /*readTime=*/16, EV_ABS, ABS_MT_POSITION_X, 100);
8769 process(mapper, 20, /*readTime=*/21, EV_ABS, ABS_MT_POSITION_Y, 100);
8770 process(mapper, 25, /*readTime=*/26, EV_SYN, SYN_REPORT, 0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008771
8772 NotifyMotionArgs args;
8773 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8774 ASSERT_EQ(26, args.readTime);
8775
Harry Cutts33476232023-01-30 19:57:29 +00008776 process(mapper, 30, /*readTime=*/31, EV_ABS, ABS_MT_POSITION_X, 110);
8777 process(mapper, 30, /*readTime=*/32, EV_ABS, ABS_MT_POSITION_Y, 220);
8778 process(mapper, 30, /*readTime=*/33, EV_SYN, SYN_REPORT, 0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008779
8780 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8781 ASSERT_EQ(33, args.readTime);
8782}
8783
8784/**
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008785 * When the viewport is not active (isActive=false), the touch mapper should be disabled and the
8786 * events should not be delivered to the listener.
8787 */
8788TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreDropped) {
8789 addConfigurationProperty("touch.deviceType", "touchScreen");
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008790 // Don't set touch.enableForInactiveViewport to verify the default behavior.
Michael Wrighta9cf4192022-12-01 23:46:39 +00008791 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008792 /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008793 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008794 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008795 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008796
8797 NotifyMotionArgs motionArgs;
8798 processPosition(mapper, 100, 100);
8799 processSync(mapper);
8800
8801 mFakeListener->assertNotifyMotionWasNotCalled();
8802}
8803
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008804/**
8805 * When the viewport is not active (isActive=false) and touch.enableForInactiveViewport is true,
8806 * the touch mapper can process the events and the events can be delivered to the listener.
8807 */
8808TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreProcessed) {
8809 addConfigurationProperty("touch.deviceType", "touchScreen");
8810 addConfigurationProperty("touch.enableForInactiveViewport", "1");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008811 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008812 /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008813 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008814 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008815 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008816
8817 NotifyMotionArgs motionArgs;
8818 processPosition(mapper, 100, 100);
8819 processSync(mapper);
8820
8821 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8822 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8823}
8824
Josh Thielene986aed2023-06-01 14:17:30 +00008825/**
8826 * When the viewport is deactivated (isActive transitions from true to false),
8827 * and touch.enableForInactiveViewport is false, touches prior to the transition
8828 * should be cancelled.
8829 */
Garfield Tanc734e4f2021-01-15 20:01:39 -08008830TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_AbortTouches) {
8831 addConfigurationProperty("touch.deviceType", "touchScreen");
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008832 addConfigurationProperty("touch.enableForInactiveViewport", "0");
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=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008835 std::optional<DisplayViewport> optionalDisplayViewport =
8836 mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
8837 ASSERT_TRUE(optionalDisplayViewport.has_value());
8838 DisplayViewport displayViewport = *optionalDisplayViewport;
8839
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008840 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008841 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008842 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Garfield Tanc734e4f2021-01-15 20:01:39 -08008843
8844 // Finger down
8845 int32_t x = 100, y = 100;
8846 processPosition(mapper, x, y);
8847 processSync(mapper);
8848
8849 NotifyMotionArgs motionArgs;
8850 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8851 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8852
8853 // Deactivate display viewport
8854 displayViewport.isActive = false;
8855 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008856 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008857
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008858 // The ongoing touch should be canceled immediately
8859 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8860 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
8861
8862 // Finger move is ignored
Garfield Tanc734e4f2021-01-15 20:01:39 -08008863 x += 10, y += 10;
8864 processPosition(mapper, x, y);
8865 processSync(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008866 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
Garfield Tanc734e4f2021-01-15 20:01:39 -08008867
8868 // Reactivate display viewport
8869 displayViewport.isActive = true;
8870 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008871 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008872
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008873 // Finger move again starts new gesture
Garfield Tanc734e4f2021-01-15 20:01:39 -08008874 x += 10, y += 10;
8875 processPosition(mapper, x, y);
8876 processSync(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008877 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8878 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008879}
8880
Josh Thielene986aed2023-06-01 14:17:30 +00008881/**
8882 * When the viewport is deactivated (isActive transitions from true to false),
8883 * and touch.enableForInactiveViewport is true, touches prior to the transition
8884 * should not be cancelled.
8885 */
8886TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_TouchesNotAborted) {
8887 addConfigurationProperty("touch.deviceType", "touchScreen");
8888 addConfigurationProperty("touch.enableForInactiveViewport", "1");
8889 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
8890 /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
8891 std::optional<DisplayViewport> optionalDisplayViewport =
8892 mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
8893 ASSERT_TRUE(optionalDisplayViewport.has_value());
8894 DisplayViewport displayViewport = *optionalDisplayViewport;
8895
8896 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8897 prepareAxes(POSITION);
8898 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
8899
8900 // Finger down
8901 int32_t x = 100, y = 100;
8902 processPosition(mapper, x, y);
8903 processSync(mapper);
8904 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8905 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
8906
8907 // Deactivate display viewport
8908 displayViewport.isActive = false;
8909 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
8910 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8911
8912 // The ongoing touch should not be canceled
8913 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
8914
8915 // Finger move is not ignored
8916 x += 10, y += 10;
8917 processPosition(mapper, x, y);
8918 processSync(mapper);
8919 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8920 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
8921
8922 // Reactivate display viewport
8923 displayViewport.isActive = true;
8924 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
8925 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8926
8927 // Finger move continues and does not start new gesture
8928 x += 10, y += 10;
8929 processPosition(mapper, x, y);
8930 processSync(mapper);
8931 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8932 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
8933}
8934
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008935TEST_F(MultiTouchInputMapperTest, VideoFrames_ReceivedByListener) {
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008936 prepareAxes(POSITION);
8937 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008938 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00008939 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008940
8941 NotifyMotionArgs motionArgs;
8942 // Unrotated video frame
8943 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8944 std::vector<TouchVideoFrame> frames{frame};
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008945 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008946 processPosition(mapper, 100, 200);
8947 processSync(mapper);
8948 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8949 ASSERT_EQ(frames, motionArgs.videoFrames);
8950
8951 // Subsequent touch events should not have any videoframes
8952 // This is implemented separately in FakeEventHub,
8953 // but that should match the behaviour of TouchVideoDevice.
8954 processPosition(mapper, 200, 200);
8955 processSync(mapper);
8956 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8957 ASSERT_EQ(std::vector<TouchVideoFrame>(), motionArgs.videoFrames);
8958}
8959
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008960TEST_F(MultiTouchInputMapperTest, VideoFrames_AreNotRotated) {
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008961 prepareAxes(POSITION);
8962 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00008963 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008964 // Unrotated video frame
8965 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8966 NotifyMotionArgs motionArgs;
8967
8968 // Test all 4 orientations
Michael Wrighta9cf4192022-12-01 23:46:39 +00008969 for (ui::Rotation orientation : ftl::enum_range<ui::Rotation>()) {
Harry Cuttsc57cd3c2024-04-24 13:52:55 +00008970 SCOPED_TRACE(StringPrintf("Orientation %s", ftl::enum_string(orientation).c_str()));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008971 clearViewports();
8972 prepareDisplay(orientation);
8973 std::vector<TouchVideoFrame> frames{frame};
8974 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
8975 processPosition(mapper, 100, 200);
8976 processSync(mapper);
8977 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8978 ASSERT_EQ(frames, motionArgs.videoFrames);
8979 }
8980}
8981
8982TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_AreRotated) {
8983 prepareAxes(POSITION);
8984 addConfigurationProperty("touch.deviceType", "touchScreen");
8985 // Since InputReader works in the un-rotated coordinate space, only devices that are not
8986 // orientation-aware are affected by display rotation.
8987 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00008988 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008989 // Unrotated video frame
8990 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8991 NotifyMotionArgs motionArgs;
8992
8993 // Test all 4 orientations
Michael Wrighta9cf4192022-12-01 23:46:39 +00008994 for (ui::Rotation orientation : ftl::enum_range<ui::Rotation>()) {
Harry Cuttsc57cd3c2024-04-24 13:52:55 +00008995 SCOPED_TRACE(StringPrintf("Orientation %s", ftl::enum_string(orientation).c_str()));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008996 clearViewports();
8997 prepareDisplay(orientation);
8998 std::vector<TouchVideoFrame> frames{frame};
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008999 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009000 processPosition(mapper, 100, 200);
9001 processSync(mapper);
9002 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009003 // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction
9004 // compared to the display. This is so that when the window transform (which contains the
9005 // display rotation) is applied later by InputDispatcher, the coordinates end up in the
9006 // window's coordinate space.
9007 frames[0].rotate(getInverseRotation(orientation));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009008 ASSERT_EQ(frames, motionArgs.videoFrames);
lilinnan687e58f2022-07-19 16:00:50 +08009009
9010 // Release finger.
9011 processSync(mapper);
9012 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009013 }
9014}
9015
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009016TEST_F(MultiTouchInputMapperTest, VideoFrames_MultipleFramesAreNotRotated) {
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009017 prepareAxes(POSITION);
9018 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00009019 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009020 // Unrotated video frames. There's no rule that they must all have the same dimensions,
9021 // so mix these.
9022 TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
9023 TouchVideoFrame frame2(3, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {1, 3});
9024 TouchVideoFrame frame3(2, 2, {10, 20, 10, 0}, {1, 4});
9025 std::vector<TouchVideoFrame> frames{frame1, frame2, frame3};
9026 NotifyMotionArgs motionArgs;
9027
Michael Wrighta9cf4192022-12-01 23:46:39 +00009028 prepareDisplay(ui::ROTATION_90);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009029 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009030 processPosition(mapper, 100, 200);
9031 processSync(mapper);
9032 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009033 ASSERT_EQ(frames, motionArgs.videoFrames);
9034}
9035
9036TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_MultipleFramesAreRotated) {
9037 prepareAxes(POSITION);
9038 addConfigurationProperty("touch.deviceType", "touchScreen");
9039 // Since InputReader works in the un-rotated coordinate space, only devices that are not
9040 // orientation-aware are affected by display rotation.
9041 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00009042 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009043 // Unrotated video frames. There's no rule that they must all have the same dimensions,
9044 // so mix these.
9045 TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
9046 TouchVideoFrame frame2(3, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {1, 3});
9047 TouchVideoFrame frame3(2, 2, {10, 20, 10, 0}, {1, 4});
9048 std::vector<TouchVideoFrame> frames{frame1, frame2, frame3};
9049 NotifyMotionArgs motionArgs;
9050
Michael Wrighta9cf4192022-12-01 23:46:39 +00009051 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009052 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
9053 processPosition(mapper, 100, 200);
9054 processSync(mapper);
9055 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9056 std::for_each(frames.begin(), frames.end(), [](TouchVideoFrame& frame) {
9057 // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction
9058 // compared to the display. This is so that when the window transform (which contains the
9059 // display rotation) is applied later by InputDispatcher, the coordinates end up in the
9060 // window's coordinate space.
Michael Wrighta9cf4192022-12-01 23:46:39 +00009061 frame.rotate(getInverseRotation(ui::ROTATION_90));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009062 });
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009063 ASSERT_EQ(frames, motionArgs.videoFrames);
9064}
9065
Arthur Hung9da14732019-09-02 16:16:58 +08009066/**
9067 * If we had defined port associations, but the viewport is not ready, the touch device would be
9068 * expected to be disabled, and it should be enabled after the viewport has found.
9069 */
9070TEST_F(MultiTouchInputMapperTest, Configure_EnabledForAssociatedDisplay) {
Arthur Hung9da14732019-09-02 16:16:58 +08009071 constexpr uint8_t hdmi2 = 1;
9072 const std::string secondaryUniqueId = "uniqueId2";
Michael Wrightfe3de7d2020-07-02 19:05:30 +01009073 constexpr ViewportType type = ViewportType::EXTERNAL;
Arthur Hung9da14732019-09-02 16:16:58 +08009074
9075 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi2);
9076
9077 addConfigurationProperty("touch.deviceType", "touchScreen");
9078 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00009079 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung9da14732019-09-02 16:16:58 +08009080
9081 ASSERT_EQ(mDevice->isEnabled(), false);
9082
9083 // Add display on hdmi2, the device should be enabled and can receive touch event.
9084 prepareSecondaryDisplay(type, hdmi2);
9085 ASSERT_EQ(mDevice->isEnabled(), true);
9086
9087 // Send a touch event.
9088 processPosition(mapper, 100, 100);
9089 processSync(mapper);
9090
9091 NotifyMotionArgs args;
9092 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9093 ASSERT_EQ(SECONDARY_DISPLAY_ID, args.displayId);
9094}
9095
Arthur Hung421eb1c2020-01-16 00:09:42 +08009096TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleSingleTouch) {
Arthur Hung421eb1c2020-01-16 00:09:42 +08009097 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009098 prepareDisplay(ui::ROTATION_0);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009099 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009100 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung421eb1c2020-01-16 00:09:42 +08009101
9102 NotifyMotionArgs motionArgs;
9103
9104 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
9105 // finger down
9106 processId(mapper, 1);
9107 processPosition(mapper, x1, y1);
9108 processSync(mapper);
9109 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9110 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009111 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009112
9113 // finger move
9114 processId(mapper, 1);
9115 processPosition(mapper, x2, y2);
9116 processSync(mapper);
9117 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9118 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009119 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009120
9121 // finger up.
9122 processId(mapper, -1);
9123 processSync(mapper);
9124 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9125 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009126 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009127
9128 // new finger down
9129 processId(mapper, 1);
9130 processPosition(mapper, x3, y3);
9131 processSync(mapper);
9132 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9133 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009134 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009135}
9136
9137/**
arthurhungcc7f9802020-04-30 17:55:40 +08009138 * Test single touch should be canceled when received the MT_TOOL_PALM event, and the following
9139 * MOVE and UP events should be ignored.
Arthur Hung421eb1c2020-01-16 00:09:42 +08009140 */
arthurhungcc7f9802020-04-30 17:55:40 +08009141TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_SinglePointer) {
Arthur Hung421eb1c2020-01-16 00:09:42 +08009142 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009143 prepareDisplay(ui::ROTATION_0);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009144 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009145 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung421eb1c2020-01-16 00:09:42 +08009146
9147 NotifyMotionArgs motionArgs;
9148
9149 // default tool type is finger
9150 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
arthurhungcc7f9802020-04-30 17:55:40 +08009151 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009152 processPosition(mapper, x1, y1);
9153 processSync(mapper);
9154 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9155 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009156 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009157
9158 // Tool changed to MT_TOOL_PALM expect sending the cancel event.
9159 processToolType(mapper, MT_TOOL_PALM);
9160 processSync(mapper);
9161 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9162 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9163
9164 // Ignore the following MOVE and UP events if had detect a palm event.
arthurhungcc7f9802020-04-30 17:55:40 +08009165 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009166 processPosition(mapper, x2, y2);
9167 processSync(mapper);
9168 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9169
9170 // finger up.
arthurhungcc7f9802020-04-30 17:55:40 +08009171 processId(mapper, INVALID_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009172 processSync(mapper);
9173 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9174
9175 // new finger down
arthurhungcc7f9802020-04-30 17:55:40 +08009176 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009177 processToolType(mapper, MT_TOOL_FINGER);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009178 processPosition(mapper, x3, y3);
9179 processSync(mapper);
9180 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9181 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009182 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009183}
9184
arthurhungbf89a482020-04-17 17:37:55 +08009185/**
arthurhungcc7f9802020-04-30 17:55:40 +08009186 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event from some finger,
9187 * and the rest active fingers could still be allowed to receive the events
arthurhungbf89a482020-04-17 17:37:55 +08009188 */
arthurhungcc7f9802020-04-30 17:55:40 +08009189TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_TwoPointers) {
arthurhungbf89a482020-04-17 17:37:55 +08009190 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009191 prepareDisplay(ui::ROTATION_0);
arthurhungbf89a482020-04-17 17:37:55 +08009192 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009193 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungbf89a482020-04-17 17:37:55 +08009194
9195 NotifyMotionArgs motionArgs;
9196
9197 // default tool type is finger
arthurhungcc7f9802020-04-30 17:55:40 +08009198 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220;
9199 processId(mapper, FIRST_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009200 processPosition(mapper, x1, y1);
9201 processSync(mapper);
9202 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9203 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009204 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungbf89a482020-04-17 17:37:55 +08009205
9206 // Second finger down.
arthurhungcc7f9802020-04-30 17:55:40 +08009207 processSlot(mapper, SECOND_SLOT);
9208 processId(mapper, SECOND_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009209 processPosition(mapper, x2, y2);
arthurhungcc7f9802020-04-30 17:55:40 +08009210 processSync(mapper);
9211 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009212 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009213 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009214
9215 // If the tool type of the first finger changes to MT_TOOL_PALM,
9216 // we expect to receive ACTION_POINTER_UP with cancel flag.
9217 processSlot(mapper, FIRST_SLOT);
9218 processId(mapper, FIRST_TRACKING_ID);
9219 processToolType(mapper, MT_TOOL_PALM);
9220 processSync(mapper);
9221 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009222 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009223 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9224
9225 // The following MOVE events of second finger should be processed.
9226 processSlot(mapper, SECOND_SLOT);
9227 processId(mapper, SECOND_TRACKING_ID);
9228 processPosition(mapper, x2 + 1, y2 + 1);
9229 processSync(mapper);
9230 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9231 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009232 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009233
9234 // First finger up. It used to be in palm mode, and we already generated ACTION_POINTER_UP for
9235 // it. Second finger receive move.
9236 processSlot(mapper, FIRST_SLOT);
9237 processId(mapper, INVALID_TRACKING_ID);
9238 processSync(mapper);
9239 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9240 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009241 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009242
9243 // Second finger keeps moving.
9244 processSlot(mapper, SECOND_SLOT);
9245 processId(mapper, SECOND_TRACKING_ID);
9246 processPosition(mapper, x2 + 2, y2 + 2);
9247 processSync(mapper);
9248 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9249 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009250 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009251
9252 // Second finger up.
9253 processId(mapper, INVALID_TRACKING_ID);
9254 processSync(mapper);
9255 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9256 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9257 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9258}
9259
9260/**
9261 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event, if only 1 finger
9262 * is active, it should send CANCEL after receiving the MT_TOOL_PALM event.
9263 */
9264TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_ShouldCancelWhenAllTouchIsPalm) {
9265 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009266 prepareDisplay(ui::ROTATION_0);
arthurhungcc7f9802020-04-30 17:55:40 +08009267 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009268 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungcc7f9802020-04-30 17:55:40 +08009269
9270 NotifyMotionArgs motionArgs;
9271
9272 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
9273 // First finger down.
9274 processId(mapper, FIRST_TRACKING_ID);
9275 processPosition(mapper, x1, y1);
9276 processSync(mapper);
9277 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9278 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009279 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009280
9281 // Second finger down.
9282 processSlot(mapper, SECOND_SLOT);
9283 processId(mapper, SECOND_TRACKING_ID);
9284 processPosition(mapper, x2, y2);
arthurhungbf89a482020-04-17 17:37:55 +08009285 processSync(mapper);
9286 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009287 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009288 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungbf89a482020-04-17 17:37:55 +08009289
arthurhungcc7f9802020-04-30 17:55:40 +08009290 // If the tool type of the first finger changes to MT_TOOL_PALM,
9291 // we expect to receive ACTION_POINTER_UP with cancel flag.
9292 processSlot(mapper, FIRST_SLOT);
9293 processId(mapper, FIRST_TRACKING_ID);
9294 processToolType(mapper, MT_TOOL_PALM);
9295 processSync(mapper);
9296 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009297 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009298 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9299
9300 // Second finger keeps moving.
9301 processSlot(mapper, SECOND_SLOT);
9302 processId(mapper, SECOND_TRACKING_ID);
9303 processPosition(mapper, x2 + 1, y2 + 1);
9304 processSync(mapper);
9305 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9306 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9307
9308 // second finger becomes palm, receive cancel due to only 1 finger is active.
9309 processId(mapper, SECOND_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009310 processToolType(mapper, MT_TOOL_PALM);
9311 processSync(mapper);
9312 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9313 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9314
arthurhungcc7f9802020-04-30 17:55:40 +08009315 // third finger down.
9316 processSlot(mapper, THIRD_SLOT);
9317 processId(mapper, THIRD_TRACKING_ID);
9318 processToolType(mapper, MT_TOOL_FINGER);
arthurhungbf89a482020-04-17 17:37:55 +08009319 processPosition(mapper, x3, y3);
9320 processSync(mapper);
arthurhungbf89a482020-04-17 17:37:55 +08009321 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9322 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009323 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009324 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009325
9326 // third finger move
9327 processId(mapper, THIRD_TRACKING_ID);
9328 processPosition(mapper, x3 + 1, y3 + 1);
9329 processSync(mapper);
9330 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9331 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9332
9333 // first finger up, third finger receive move.
9334 processSlot(mapper, FIRST_SLOT);
9335 processId(mapper, INVALID_TRACKING_ID);
9336 processSync(mapper);
9337 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9338 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009339 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009340
9341 // second finger up, third finger receive move.
9342 processSlot(mapper, SECOND_SLOT);
9343 processId(mapper, INVALID_TRACKING_ID);
9344 processSync(mapper);
9345 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9346 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009347 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009348
9349 // third finger up.
9350 processSlot(mapper, THIRD_SLOT);
9351 processId(mapper, INVALID_TRACKING_ID);
9352 processSync(mapper);
9353 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9354 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9355 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9356}
9357
9358/**
9359 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event from some finger,
9360 * and the active finger could still be allowed to receive the events
9361 */
9362TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_KeepFirstPointer) {
9363 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009364 prepareDisplay(ui::ROTATION_0);
arthurhungcc7f9802020-04-30 17:55:40 +08009365 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009366 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungcc7f9802020-04-30 17:55:40 +08009367
9368 NotifyMotionArgs motionArgs;
9369
9370 // default tool type is finger
9371 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220;
9372 processId(mapper, FIRST_TRACKING_ID);
9373 processPosition(mapper, x1, y1);
9374 processSync(mapper);
9375 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9376 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009377 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009378
9379 // Second finger down.
9380 processSlot(mapper, SECOND_SLOT);
9381 processId(mapper, SECOND_TRACKING_ID);
9382 processPosition(mapper, x2, y2);
9383 processSync(mapper);
9384 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009385 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009386 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009387
9388 // If the tool type of the second finger changes to MT_TOOL_PALM,
9389 // we expect to receive ACTION_POINTER_UP with cancel flag.
9390 processId(mapper, SECOND_TRACKING_ID);
9391 processToolType(mapper, MT_TOOL_PALM);
9392 processSync(mapper);
9393 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009394 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009395 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9396
9397 // The following MOVE event should be processed.
9398 processSlot(mapper, FIRST_SLOT);
9399 processId(mapper, FIRST_TRACKING_ID);
9400 processPosition(mapper, x1 + 1, y1 + 1);
9401 processSync(mapper);
9402 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9403 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009404 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009405
9406 // second finger up.
9407 processSlot(mapper, SECOND_SLOT);
9408 processId(mapper, INVALID_TRACKING_ID);
9409 processSync(mapper);
9410 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9411 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9412
9413 // first finger keep moving
9414 processSlot(mapper, FIRST_SLOT);
9415 processId(mapper, FIRST_TRACKING_ID);
9416 processPosition(mapper, x1 + 2, y1 + 2);
9417 processSync(mapper);
9418 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9419 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9420
9421 // first finger up.
9422 processId(mapper, INVALID_TRACKING_ID);
9423 processSync(mapper);
9424 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9425 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9426 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
arthurhungbf89a482020-04-17 17:37:55 +08009427}
9428
Arthur Hung9ad18942021-06-19 02:04:46 +00009429/**
9430 * Test multi-touch should sent ACTION_POINTER_UP/ACTION_UP when received the INVALID_TRACKING_ID,
9431 * to prevent the driver side may send unexpected data after set tracking id as INVALID_TRACKING_ID
9432 * cause slot be valid again.
9433 */
9434TEST_F(MultiTouchInputMapperTest, Process_MultiTouch_WithInvalidTrackingId) {
9435 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009436 prepareDisplay(ui::ROTATION_0);
Arthur Hung9ad18942021-06-19 02:04:46 +00009437 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009438 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung9ad18942021-06-19 02:04:46 +00009439
9440 NotifyMotionArgs motionArgs;
9441
9442 constexpr int32_t x1 = 100, y1 = 200, x2 = 0, y2 = 0;
9443 // First finger down.
9444 processId(mapper, FIRST_TRACKING_ID);
9445 processPosition(mapper, x1, y1);
9446 processPressure(mapper, RAW_PRESSURE_MAX);
9447 processSync(mapper);
9448 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9449 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009450 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009451
9452 // First finger move.
9453 processId(mapper, FIRST_TRACKING_ID);
9454 processPosition(mapper, x1 + 1, y1 + 1);
9455 processPressure(mapper, RAW_PRESSURE_MAX);
9456 processSync(mapper);
9457 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9458 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009459 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009460
9461 // Second finger down.
9462 processSlot(mapper, SECOND_SLOT);
9463 processId(mapper, SECOND_TRACKING_ID);
9464 processPosition(mapper, x2, y2);
9465 processPressure(mapper, RAW_PRESSURE_MAX);
9466 processSync(mapper);
9467 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009468 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009469 ASSERT_EQ(uint32_t(2), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009470
9471 // second finger up with some unexpected data.
9472 processSlot(mapper, SECOND_SLOT);
9473 processId(mapper, INVALID_TRACKING_ID);
9474 processPosition(mapper, x2, y2);
9475 processSync(mapper);
9476 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009477 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009478 ASSERT_EQ(uint32_t(2), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009479
9480 // first finger up with some unexpected data.
9481 processSlot(mapper, FIRST_SLOT);
9482 processId(mapper, INVALID_TRACKING_ID);
9483 processPosition(mapper, x2, y2);
9484 processPressure(mapper, RAW_PRESSURE_MAX);
9485 processSync(mapper);
9486 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9487 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009488 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009489}
9490
Arpit Singh4b4a4572023-11-24 18:19:56 +00009491TEST_F(MultiTouchInputMapperTest, Reset_RepopulatesMultiTouchState) {
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009492 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009493 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009494 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009495 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009496
9497 // First finger down.
Arpit Singh4b4a4572023-11-24 18:19:56 +00009498 constexpr int32_t x1 = 100, y1 = 200, x2 = 300, y2 = 400;
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009499 processId(mapper, FIRST_TRACKING_ID);
Arpit Singh4b4a4572023-11-24 18:19:56 +00009500 processPosition(mapper, x1, y1);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009501 processPressure(mapper, RAW_PRESSURE_MAX);
9502 processSync(mapper);
9503 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9504 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
9505
9506 // Second finger down.
9507 processSlot(mapper, SECOND_SLOT);
9508 processId(mapper, SECOND_TRACKING_ID);
Arpit Singh4b4a4572023-11-24 18:19:56 +00009509 processPosition(mapper, x2, y2);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009510 processPressure(mapper, RAW_PRESSURE_MAX);
9511 processSync(mapper);
9512 ASSERT_NO_FATAL_FAILURE(
9513 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(ACTION_POINTER_1_DOWN)));
9514
Arpit Singh4b4a4572023-11-24 18:19:56 +00009515 // Set MT Slot state to be repopulated for the required slots
9516 std::vector<int32_t> mtSlotValues(RAW_SLOT_MAX + 1, -1);
9517 mtSlotValues[0] = FIRST_TRACKING_ID;
9518 mtSlotValues[1] = SECOND_TRACKING_ID;
9519 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_TRACKING_ID, mtSlotValues);
9520
9521 mtSlotValues[0] = x1;
9522 mtSlotValues[1] = x2;
9523 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_POSITION_X, mtSlotValues);
9524
9525 mtSlotValues[0] = y1;
9526 mtSlotValues[1] = y2;
9527 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_POSITION_Y, mtSlotValues);
9528
9529 mtSlotValues[0] = RAW_PRESSURE_MAX;
9530 mtSlotValues[1] = RAW_PRESSURE_MAX;
9531 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_PRESSURE, mtSlotValues);
9532
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009533 // Reset the mapper. When the mapper is reset, we expect the current multi-touch state to be
Arpit Singh4b4a4572023-11-24 18:19:56 +00009534 // repopulated. Resetting should cancel the ongoing gesture.
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00009535 resetMapper(mapper, ARBITRARY_TIME);
9536 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9537 WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009538
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009539 // Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
9540 // the existing touch state to generate a down event.
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009541 processPosition(mapper, 301, 302);
9542 processSync(mapper);
9543 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9544 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPressure(1.f))));
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009545 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9546 AllOf(WithMotionAction(ACTION_POINTER_1_DOWN), WithPressure(1.f))));
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009547
9548 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9549}
9550
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009551TEST_F(MultiTouchInputMapperTest, Reset_PreservesLastTouchState_NoPointersDown) {
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009552 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009553 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009554 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009555 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009556
9557 // First finger touches down and releases.
9558 processId(mapper, FIRST_TRACKING_ID);
9559 processPosition(mapper, 100, 200);
9560 processPressure(mapper, RAW_PRESSURE_MAX);
9561 processSync(mapper);
9562 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9563 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
9564 processId(mapper, INVALID_TRACKING_ID);
9565 processSync(mapper);
9566 ASSERT_NO_FATAL_FAILURE(
9567 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
9568
9569 // Reset the mapper. When the mapper is reset, we expect it to restore the latest
9570 // raw state where no pointers are down.
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00009571 resetMapper(mapper, ARBITRARY_TIME);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009572 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9573
9574 // Send an empty sync frame. Since there are no pointers, no events are generated.
9575 processSync(mapper);
9576 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9577}
9578
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009579TEST_F(MultiTouchInputMapperTest, StylusSourceIsAddedDynamicallyFromToolType) {
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009580 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009581 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009582 prepareAxes(POSITION | ID | SLOT | PRESSURE | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009583 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009584 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009585
9586 // Even if the device supports reporting the ABS_MT_TOOL_TYPE axis, which could give it the
9587 // ability to report MT_TOOL_PEN, we do not report the device as coming from a stylus source.
9588 // Due to limitations in the evdev protocol, we cannot say for certain that a device is capable
9589 // of reporting stylus events just because it supports ABS_MT_TOOL_TYPE.
9590 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
9591
9592 // However, if the device ever ends up reporting an event with MT_TOOL_PEN, it should be
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009593 // reported with the stylus source.
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009594 processId(mapper, FIRST_TRACKING_ID);
9595 processToolType(mapper, MT_TOOL_PEN);
9596 processPosition(mapper, 100, 200);
9597 processPressure(mapper, RAW_PRESSURE_MAX);
9598 processSync(mapper);
9599 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9600 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
9601 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009602 WithToolType(ToolType::STYLUS))));
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009603
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009604 // Now that we know the device supports styluses, ensure that the device is re-configured with
9605 // the stylus source.
9606 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, mapper.getSources());
9607 {
9608 const auto& devices = mReader->getInputDevices();
9609 auto deviceInfo =
9610 std::find_if(devices.begin(), devices.end(),
9611 [](const InputDeviceInfo& info) { return info.getId() == DEVICE_ID; });
9612 LOG_ALWAYS_FATAL_IF(deviceInfo == devices.end(), "Cannot find InputDevice");
9613 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, deviceInfo->getSources());
9614 }
9615
9616 // Ensure the device was not reset to prevent interruptions of any ongoing gestures.
9617 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
9618
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009619 processId(mapper, INVALID_TRACKING_ID);
9620 processSync(mapper);
9621 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9622 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
9623 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009624 WithToolType(ToolType::STYLUS))));
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009625}
9626
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009627// --- MultiTouchInputMapperTest_ExternalDevice ---
9628
9629class MultiTouchInputMapperTest_ExternalDevice : public MultiTouchInputMapperTest {
9630protected:
Chris Yea52ade12020-08-27 16:49:20 -07009631 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL); }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009632};
9633
9634/**
9635 * Expect fallback to internal viewport if device is external and external viewport is not present.
9636 */
9637TEST_F(MultiTouchInputMapperTest_ExternalDevice, Viewports_Fallback) {
9638 prepareAxes(POSITION);
9639 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009640 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00009641 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009642
9643 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
9644
9645 NotifyMotionArgs motionArgs;
9646
9647 // Expect the event to be sent to the internal viewport,
9648 // because an external viewport is not present.
9649 processPosition(mapper, 100, 100);
9650 processSync(mapper);
9651 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Linnan Li13bf76a2024-05-05 19:18:02 +08009652 ASSERT_EQ(ui::ADISPLAY_ID_DEFAULT, motionArgs.displayId);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009653
9654 // Expect the event to be sent to the external viewport if it is present.
Michael Wrightfe3de7d2020-07-02 19:05:30 +01009655 prepareSecondaryDisplay(ViewportType::EXTERNAL);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009656 processPosition(mapper, 100, 100);
9657 processSync(mapper);
9658 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9659 ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
9660}
Arthur Hung4197f6b2020-03-16 15:39:59 +08009661
Prabir Pradhan3ed7e352024-05-03 23:59:43 +00009662// TODO(b/281840344): Remove the test when the old touchpad stack is removed. It is currently
9663// unclear what the behavior of the touchpad logic in TouchInputMapper should do after the
9664// PointerChoreographer refactor.
9665TEST_F(MultiTouchInputMapperTest, DISABLED_Process_TouchpadPointer) {
Harry Cutts8722be92024-04-05 14:46:05 +00009666 // prepare device
Michael Wrighta9cf4192022-12-01 23:46:39 +00009667 prepareDisplay(ui::ROTATION_0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009668 prepareAxes(POSITION | ID | SLOT);
9669 mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
9670 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00009671 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009672 // run uncaptured pointer tests - pushes out generic events
9673 // FINGER 0 DOWN
9674 processId(mapper, 3);
9675 processPosition(mapper, 100, 100);
9676 processKey(mapper, BTN_TOUCH, 1);
9677 processSync(mapper);
9678
9679 // start at (100,100), cursor should be at (0,0) * scale
9680 NotifyMotionArgs args;
9681 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9682 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
9683 ASSERT_NO_FATAL_FAILURE(
9684 assertPointerCoords(args.pointerCoords[0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
9685
9686 // FINGER 0 MOVE
9687 processPosition(mapper, 200, 200);
9688 processSync(mapper);
9689
9690 // compute scaling to help with touch position checking
9691 float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
9692 float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
9693 float scale =
9694 mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
9695
9696 // translate from (100,100) -> (200,200), cursor should have changed to (100,100) * scale)
9697 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9698 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
9699 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], 100 * scale, 100 * scale, 0,
9700 0, 0, 0, 0, 0, 0, 0));
LiZhihong758eb562022-11-03 15:28:29 +08009701
9702 // BUTTON DOWN
9703 processKey(mapper, BTN_LEFT, 1);
9704 processSync(mapper);
9705
9706 // touchinputmapper design sends a move before button press
9707 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9708 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
9709 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9710 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, args.action);
9711
9712 // BUTTON UP
9713 processKey(mapper, BTN_LEFT, 0);
9714 processSync(mapper);
9715
9716 // touchinputmapper design sends a move after button release
9717 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9718 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, args.action);
9719 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9720 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009721}
9722
Harry Cutts8722be92024-04-05 14:46:05 +00009723TEST_F(MultiTouchInputMapperTest, Touchpad_GetSources) {
Michael Wrighta9cf4192022-12-01 23:46:39 +00009724 prepareDisplay(ui::ROTATION_0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009725 prepareAxes(POSITION | ID | SLOT);
9726 mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
Hiroki Sato25040232024-02-22 17:21:22 +09009727 mFakePolicy->setPointerCapture(/*window=*/nullptr);
Arpit Singha8c236b2023-04-25 13:56:05 +00009728 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009729
Josep del Río2d8c79a2023-01-23 19:33:50 +00009730 // uncaptured touchpad should be a pointer device
9731 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009732}
9733
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009734// --- BluetoothMultiTouchInputMapperTest ---
9735
9736class BluetoothMultiTouchInputMapperTest : public MultiTouchInputMapperTest {
9737protected:
9738 void SetUp() override {
9739 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL, BUS_BLUETOOTH);
9740 }
9741};
9742
9743TEST_F(BluetoothMultiTouchInputMapperTest, TimestampSmoothening) {
9744 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009745 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009746 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009747 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009748
9749 nsecs_t kernelEventTime = ARBITRARY_TIME;
9750 nsecs_t expectedEventTime = ARBITRARY_TIME;
9751 // Touch down.
9752 processId(mapper, FIRST_TRACKING_ID);
9753 processPosition(mapper, 100, 200);
9754 processPressure(mapper, RAW_PRESSURE_MAX);
9755 processSync(mapper, ARBITRARY_TIME);
9756 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9757 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithEventTime(ARBITRARY_TIME))));
9758
9759 // Process several events that come in quick succession, according to their timestamps.
9760 for (int i = 0; i < 3; i++) {
9761 constexpr static nsecs_t delta = ms2ns(1);
9762 static_assert(delta < MIN_BLUETOOTH_TIMESTAMP_DELTA);
9763 kernelEventTime += delta;
9764 expectedEventTime += MIN_BLUETOOTH_TIMESTAMP_DELTA;
9765
9766 processPosition(mapper, 101 + i, 201 + i);
9767 processSync(mapper, kernelEventTime);
9768 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9769 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
9770 WithEventTime(expectedEventTime))));
9771 }
9772
9773 // Release the touch.
9774 processId(mapper, INVALID_TRACKING_ID);
9775 processPressure(mapper, RAW_PRESSURE_MIN);
9776 processSync(mapper, ARBITRARY_TIME + ms2ns(50));
9777 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9778 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
9779 WithEventTime(ARBITRARY_TIME + ms2ns(50)))));
9780}
9781
9782// --- MultiTouchPointerModeTest ---
9783
HQ Liue6983c72022-04-19 22:14:56 +00009784class MultiTouchPointerModeTest : public MultiTouchInputMapperTest {
9785protected:
9786 float mPointerMovementScale;
9787 float mPointerXZoomScale;
9788 void preparePointerMode(int xAxisResolution, int yAxisResolution) {
9789 addConfigurationProperty("touch.deviceType", "pointer");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009790 prepareDisplay(ui::ROTATION_0);
HQ Liue6983c72022-04-19 22:14:56 +00009791
9792 prepareAxes(POSITION);
9793 prepareAbsoluteAxisResolution(xAxisResolution, yAxisResolution);
9794 // In order to enable swipe and freeform gesture in pointer mode, pointer capture
9795 // needs to be disabled, and the pointer gesture needs to be enabled.
Hiroki Sato25040232024-02-22 17:21:22 +09009796 mFakePolicy->setPointerCapture(/*window=*/nullptr);
HQ Liue6983c72022-04-19 22:14:56 +00009797 mFakePolicy->setPointerGestureEnabled(true);
HQ Liue6983c72022-04-19 22:14:56 +00009798
9799 float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
9800 float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
9801 mPointerMovementScale =
9802 mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
9803 mPointerXZoomScale =
9804 mFakePolicy->getPointerGestureZoomSpeedRatio() * displayDiagonal / rawDiagonal;
9805 }
9806
9807 void prepareAbsoluteAxisResolution(int xAxisResolution, int yAxisResolution) {
9808 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX,
9809 /*flat*/ 0,
9810 /*fuzz*/ 0, /*resolution*/ xAxisResolution);
9811 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX,
9812 /*flat*/ 0,
9813 /*fuzz*/ 0, /*resolution*/ yAxisResolution);
9814 }
9815};
9816
9817/**
9818 * Two fingers down on a pointer mode touch pad. The width
9819 * of the two finger is larger than 1/4 of the touch pack diagnal length. However, it
9820 * is smaller than the fixed min physical length 30mm. Two fingers' distance must
9821 * be greater than the both value to be freeform gesture, so that after two
9822 * fingers start to move downwards, the gesture should be swipe.
9823 */
9824TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthSwipe) {
9825 // The min freeform gesture width is 25units/mm x 30mm = 750
9826 // which is greater than fraction of the diagnal length of the touchpad (349).
9827 // Thus, MaxSwipWidth is 750.
Harry Cutts33476232023-01-30 19:57:29 +00009828 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +00009829 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009830 NotifyMotionArgs motionArgs;
9831
9832 // Two fingers down at once.
9833 // The two fingers are 450 units apart, expects the current gesture to be PRESS
9834 // Pointer's initial position is used the [0,0] coordinate.
9835 int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125;
9836
9837 processId(mapper, FIRST_TRACKING_ID);
9838 processPosition(mapper, x1, y1);
9839 processMTSync(mapper);
9840 processId(mapper, SECOND_TRACKING_ID);
9841 processPosition(mapper, x2, y2);
9842 processMTSync(mapper);
9843 processSync(mapper);
9844
9845 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009846 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009847 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009848 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009849 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009850 ASSERT_NO_FATAL_FAILURE(
9851 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9852
9853 // It should be recognized as a SWIPE gesture when two fingers start to move down,
9854 // that there should be 1 pointer.
9855 int32_t movingDistance = 200;
9856 y1 += movingDistance;
9857 y2 += movingDistance;
9858
9859 processId(mapper, FIRST_TRACKING_ID);
9860 processPosition(mapper, x1, y1);
9861 processMTSync(mapper);
9862 processId(mapper, SECOND_TRACKING_ID);
9863 processPosition(mapper, x2, y2);
9864 processMTSync(mapper);
9865 processSync(mapper);
9866
9867 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009868 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009869 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009870 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009871 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009872 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
9873 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9874 0, 0, 0, 0));
9875}
9876
9877/**
9878 * Two fingers down on a pointer mode touch pad. The width of the two finger is larger
9879 * than the minimum freeform gesture width, 30mm. However, it is smaller than 1/4 of
9880 * the touch pack diagnal length. Two fingers' distance must be greater than the both
9881 * value to be freeform gesture, so that after two fingers start to move downwards,
9882 * the gesture should be swipe.
9883 */
9884TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthLowResolutionSwipe) {
9885 // The min freeform gesture width is 5units/mm x 30mm = 150
9886 // which is greater than fraction of the diagnal length of the touchpad (349).
9887 // Thus, MaxSwipWidth is the fraction of the diagnal length, 349.
Harry Cutts33476232023-01-30 19:57:29 +00009888 preparePointerMode(/*xResolution=*/5, /*yResolution=*/5);
Arpit Singha8c236b2023-04-25 13:56:05 +00009889 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009890 NotifyMotionArgs motionArgs;
9891
9892 // Two fingers down at once.
9893 // The two fingers are 250 units apart, expects the current gesture to be PRESS
9894 // Pointer's initial position is used the [0,0] coordinate.
9895 int32_t x1 = 100, y1 = 125, x2 = 350, y2 = 125;
9896
9897 processId(mapper, FIRST_TRACKING_ID);
9898 processPosition(mapper, x1, y1);
9899 processMTSync(mapper);
9900 processId(mapper, SECOND_TRACKING_ID);
9901 processPosition(mapper, x2, y2);
9902 processMTSync(mapper);
9903 processSync(mapper);
9904
9905 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009906 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009907 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009908 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009909 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009910 ASSERT_NO_FATAL_FAILURE(
9911 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9912
9913 // It should be recognized as a SWIPE gesture when two fingers start to move down,
9914 // and there should be 1 pointer.
9915 int32_t movingDistance = 200;
9916 y1 += movingDistance;
9917 y2 += movingDistance;
9918
9919 processId(mapper, FIRST_TRACKING_ID);
9920 processPosition(mapper, x1, y1);
9921 processMTSync(mapper);
9922 processId(mapper, SECOND_TRACKING_ID);
9923 processPosition(mapper, x2, y2);
9924 processMTSync(mapper);
9925 processSync(mapper);
9926
9927 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009928 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009929 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009930 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009931 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009932 // New coordinate is the scaled relative coordinate from the initial coordinate.
9933 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
9934 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9935 0, 0, 0, 0));
9936}
9937
9938/**
9939 * Touch the touch pad with two fingers with a distance wider than the minimum freeform
9940 * gesture width and 1/4 of the diagnal length of the touchpad. Expect to receive
9941 * freeform gestures after two fingers start to move downwards.
9942 */
9943TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthFreeform) {
Harry Cutts33476232023-01-30 19:57:29 +00009944 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +00009945 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009946
9947 NotifyMotionArgs motionArgs;
9948
9949 // Two fingers down at once. Wider than the max swipe width.
9950 // The gesture is expected to be PRESS, then transformed to FREEFORM
9951 int32_t x1 = 100, y1 = 125, x2 = 900, y2 = 125;
9952
9953 processId(mapper, FIRST_TRACKING_ID);
9954 processPosition(mapper, x1, y1);
9955 processMTSync(mapper);
9956 processId(mapper, SECOND_TRACKING_ID);
9957 processPosition(mapper, x2, y2);
9958 processMTSync(mapper);
9959 processSync(mapper);
9960
9961 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009962 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009963 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009964 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009965 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009966 // One pointer for PRESS, and its coordinate is used as the origin for pointer coordinates.
9967 ASSERT_NO_FATAL_FAILURE(
9968 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9969
9970 int32_t movingDistance = 200;
9971
9972 // Move two fingers down, expect a cancel event because gesture is changing to freeform,
9973 // then two down events for two pointers.
9974 y1 += movingDistance;
9975 y2 += movingDistance;
9976
9977 processId(mapper, FIRST_TRACKING_ID);
9978 processPosition(mapper, x1, y1);
9979 processMTSync(mapper);
9980 processId(mapper, SECOND_TRACKING_ID);
9981 processPosition(mapper, x2, y2);
9982 processMTSync(mapper);
9983 processSync(mapper);
9984
9985 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9986 // The previous PRESS gesture is cancelled, because it is transformed to freeform
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009987 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009988 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9989 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009990 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009991 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009992 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
9993 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009994 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009995 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009996 ASSERT_EQ(2U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009997 ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN, motionArgs.action & AMOTION_EVENT_ACTION_MASK);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009998 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009999 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +000010000 // Two pointers' scaled relative coordinates from their initial centroid.
10001 // Initial y coordinates are 0 as y1 and y2 have the same value.
10002 float cookedX1 = (x1 - x2) / 2 * mPointerXZoomScale;
10003 float cookedX2 = (x2 - x1) / 2 * mPointerXZoomScale;
10004 // When pointers move, the new coordinates equal to the initial coordinates plus
10005 // scaled moving distance.
10006 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
10007 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
10008 0, 0, 0, 0));
10009 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], cookedX2,
10010 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
10011 0, 0, 0, 0));
10012
10013 // Move two fingers down again, expect one MOVE motion event.
10014 y1 += movingDistance;
10015 y2 += movingDistance;
10016
10017 processId(mapper, FIRST_TRACKING_ID);
10018 processPosition(mapper, x1, y1);
10019 processMTSync(mapper);
10020 processId(mapper, SECOND_TRACKING_ID);
10021 processPosition(mapper, x2, y2);
10022 processMTSync(mapper);
10023 processSync(mapper);
10024
10025 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010026 ASSERT_EQ(2U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010027 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010028 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +000010029 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +000010030 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
10031 movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
10032 0, 0, 0, 0, 0));
10033 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], cookedX2,
10034 movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
10035 0, 0, 0, 0, 0));
10036}
10037
Harry Cutts39b7ca22022-10-05 15:55:48 +000010038TEST_F(MultiTouchPointerModeTest, TwoFingerSwipeOffsets) {
Harry Cutts33476232023-01-30 19:57:29 +000010039 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +000010040 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Harry Cutts39b7ca22022-10-05 15:55:48 +000010041 NotifyMotionArgs motionArgs;
10042
10043 // Place two fingers down.
10044 int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125;
10045
10046 processId(mapper, FIRST_TRACKING_ID);
10047 processPosition(mapper, x1, y1);
10048 processMTSync(mapper);
10049 processId(mapper, SECOND_TRACKING_ID);
10050 processPosition(mapper, x2, y2);
10051 processMTSync(mapper);
10052 processSync(mapper);
10053
10054 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010055 ASSERT_EQ(1U, motionArgs.getPointerCount());
Harry Cutts39b7ca22022-10-05 15:55:48 +000010056 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
10057 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
10058 ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET));
10059 ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET));
10060
10061 // Move the two fingers down and to the left.
10062 int32_t movingDistance = 200;
10063 x1 -= movingDistance;
10064 y1 += movingDistance;
10065 x2 -= movingDistance;
10066 y2 += movingDistance;
10067
10068 processId(mapper, FIRST_TRACKING_ID);
10069 processPosition(mapper, x1, y1);
10070 processMTSync(mapper);
10071 processId(mapper, SECOND_TRACKING_ID);
10072 processPosition(mapper, x2, y2);
10073 processMTSync(mapper);
10074 processSync(mapper);
10075
10076 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010077 ASSERT_EQ(1U, motionArgs.getPointerCount());
Harry Cutts39b7ca22022-10-05 15:55:48 +000010078 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
10079 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
10080 ASSERT_LT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET), 0);
10081 ASSERT_GT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET), 0);
10082}
10083
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010084TEST_F(MultiTouchPointerModeTest, WhenViewportActiveStatusChanged_PointerGestureIsReset) {
Harry Cutts33476232023-01-30 19:57:29 +000010085 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010086 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +000010087 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010088 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
10089
10090 // Start a stylus gesture.
10091 processKey(mapper, BTN_TOOL_PEN, 1);
10092 processId(mapper, FIRST_TRACKING_ID);
10093 processPosition(mapper, 100, 200);
10094 processSync(mapper);
10095 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10096 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
10097 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010098 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010099 // TODO(b/257078296): Pointer mode generates extra event.
10100 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10101 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
10102 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010103 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010104 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
10105
10106 // Make the viewport inactive. This will put the device in disabled mode, and the ongoing stylus
10107 // gesture should be disabled.
10108 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
10109 viewport->isActive = false;
10110 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +000010111 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010112 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10113 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
10114 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010115 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010116 // TODO(b/257078296): Pointer mode generates extra event.
10117 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10118 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
10119 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010120 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010121 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
10122}
10123
Arthur Hung6d5b4b22022-01-21 07:21:10 +000010124// --- JoystickInputMapperTest ---
10125
10126class JoystickInputMapperTest : public InputMapperTest {
10127protected:
10128 static const int32_t RAW_X_MIN;
10129 static const int32_t RAW_X_MAX;
10130 static const int32_t RAW_Y_MIN;
10131 static const int32_t RAW_Y_MAX;
10132
10133 void SetUp() override {
10134 InputMapperTest::SetUp(InputDeviceClass::JOYSTICK | InputDeviceClass::EXTERNAL);
10135 }
10136 void prepareAxes() {
10137 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
10138 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
10139 }
10140
10141 void processAxis(JoystickInputMapper& mapper, int32_t axis, int32_t value) {
10142 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, axis, value);
10143 }
10144
10145 void processSync(JoystickInputMapper& mapper) {
10146 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
10147 }
10148
Michael Wrighta9cf4192022-12-01 23:46:39 +000010149 void prepareVirtualDisplay(ui::Rotation orientation) {
Arthur Hung6d5b4b22022-01-21 07:21:10 +000010150 setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH,
10151 VIRTUAL_DISPLAY_HEIGHT, orientation, VIRTUAL_DISPLAY_UNIQUE_ID,
10152 NO_PORT, ViewportType::VIRTUAL);
10153 }
10154};
10155
10156const int32_t JoystickInputMapperTest::RAW_X_MIN = -32767;
10157const int32_t JoystickInputMapperTest::RAW_X_MAX = 32767;
10158const int32_t JoystickInputMapperTest::RAW_Y_MIN = -32767;
10159const int32_t JoystickInputMapperTest::RAW_Y_MAX = 32767;
10160
10161TEST_F(JoystickInputMapperTest, Configure_AssignsDisplayUniqueId) {
10162 prepareAxes();
Arpit Singhae876352023-04-26 14:16:50 +000010163 JoystickInputMapper& mapper = constructAndAddMapper<JoystickInputMapper>();
Arthur Hung6d5b4b22022-01-21 07:21:10 +000010164
10165 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID);
10166
Michael Wrighta9cf4192022-12-01 23:46:39 +000010167 prepareVirtualDisplay(ui::ROTATION_0);
Arthur Hung6d5b4b22022-01-21 07:21:10 +000010168
10169 // Send an axis event
10170 processAxis(mapper, ABS_X, 100);
10171 processSync(mapper);
10172
10173 NotifyMotionArgs args;
10174 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
10175 ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId);
10176
10177 // Send another axis event
10178 processAxis(mapper, ABS_Y, 100);
10179 processSync(mapper);
10180
10181 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
10182 ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId);
10183}
10184
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010185// --- PeripheralControllerTest ---
Chris Yee2b1e5c2021-03-10 22:45:12 -080010186
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010187class PeripheralControllerTest : public testing::Test {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010188protected:
10189 static const char* DEVICE_NAME;
10190 static const char* DEVICE_LOCATION;
10191 static const int32_t DEVICE_ID;
10192 static const int32_t DEVICE_GENERATION;
10193 static const int32_t DEVICE_CONTROLLER_NUMBER;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010194 static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010195 static const int32_t EVENTHUB_ID;
10196
10197 std::shared_ptr<FakeEventHub> mFakeEventHub;
10198 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010199 std::unique_ptr<TestInputListener> mFakeListener;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010200 std::unique_ptr<InstrumentedInputReader> mReader;
10201 std::shared_ptr<InputDevice> mDevice;
10202
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010203 virtual void SetUp(ftl::Flags<InputDeviceClass> classes) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010204 mFakeEventHub = std::make_unique<FakeEventHub>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010205 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010206 mFakeListener = std::make_unique<TestInputListener>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010207 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010208 *mFakeListener);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010209 mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes);
10210 }
10211
10212 void SetUp() override { SetUp(DEVICE_CLASSES); }
10213
10214 void TearDown() override {
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010215 mFakeListener.reset();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010216 mFakePolicy.clear();
10217 }
10218
Chris Yee2b1e5c2021-03-10 22:45:12 -080010219 std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
10220 const std::string& location, int32_t eventHubId,
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010221 ftl::Flags<InputDeviceClass> classes) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010222 InputDeviceIdentifier identifier;
10223 identifier.name = name;
10224 identifier.location = location;
10225 std::shared_ptr<InputDevice> device =
10226 std::make_shared<InputDevice>(mReader->getContext(), deviceId, DEVICE_GENERATION,
10227 identifier);
10228 mReader->pushNextDevice(device);
10229 mFakeEventHub->addDevice(eventHubId, name, classes);
10230 mReader->loopOnce();
10231 return device;
10232 }
10233
10234 template <class T, typename... Args>
10235 T& addControllerAndConfigure(Args... args) {
10236 T& controller = mDevice->addController<T>(EVENTHUB_ID, args...);
10237
10238 return controller;
10239 }
10240};
10241
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010242const char* PeripheralControllerTest::DEVICE_NAME = "device";
10243const char* PeripheralControllerTest::DEVICE_LOCATION = "BLUETOOTH";
10244const int32_t PeripheralControllerTest::DEVICE_ID = END_RESERVED_ID + 1000;
10245const int32_t PeripheralControllerTest::DEVICE_GENERATION = 2;
10246const int32_t PeripheralControllerTest::DEVICE_CONTROLLER_NUMBER = 0;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010247const ftl::Flags<InputDeviceClass> PeripheralControllerTest::DEVICE_CLASSES =
10248 ftl::Flags<InputDeviceClass>(0); // not needed for current tests
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010249const int32_t PeripheralControllerTest::EVENTHUB_ID = 1;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010250
10251// --- BatteryControllerTest ---
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010252class BatteryControllerTest : public PeripheralControllerTest {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010253protected:
10254 void SetUp() override {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010255 PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::BATTERY);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010256 }
10257};
10258
10259TEST_F(BatteryControllerTest, GetBatteryCapacity) {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010260 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010261
Harry Cuttsa5b71292022-11-28 12:56:17 +000010262 ASSERT_TRUE(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY));
10263 ASSERT_EQ(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY).value_or(-1),
10264 FakeEventHub::BATTERY_CAPACITY);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010265}
10266
10267TEST_F(BatteryControllerTest, GetBatteryStatus) {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010268 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010269
Harry Cuttsa5b71292022-11-28 12:56:17 +000010270 ASSERT_TRUE(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY));
10271 ASSERT_EQ(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY).value_or(-1),
10272 FakeEventHub::BATTERY_STATUS);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010273}
10274
10275// --- LightControllerTest ---
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010276class LightControllerTest : public PeripheralControllerTest {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010277protected:
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010278 void SetUp() override {
10279 PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::LIGHT);
10280 }
Chris Yee2b1e5c2021-03-10 22:45:12 -080010281};
10282
Chris Ye85758332021-05-16 23:05:17 -070010283TEST_F(LightControllerTest, MonoLight) {
10284 RawLightInfo infoMono = {.id = 1,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010285 .name = "mono_light",
Chris Ye85758332021-05-16 23:05:17 -070010286 .maxBrightness = 255,
10287 .flags = InputLightClass::BRIGHTNESS,
10288 .path = ""};
10289 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010290
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010291 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010292 InputDeviceInfo info;
10293 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010294 std::vector<InputDeviceLightInfo> lights = info.getLights();
10295 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010296 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10297 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10298
10299 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_BRIGHTNESS));
10300 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_BRIGHTNESS);
10301}
10302
DingYong99f2c3c2023-12-20 15:46:06 +080010303TEST_F(LightControllerTest, MonoKeyboardMuteLight) {
10304 RawLightInfo infoMono = {.id = 1,
10305 .name = "mono_keyboard_mute",
10306 .maxBrightness = 255,
10307 .flags = InputLightClass::BRIGHTNESS |
10308 InputLightClass::KEYBOARD_MIC_MUTE,
10309 .path = ""};
10310 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10311
10312 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10313 std::list<NotifyArgs> unused =
10314 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10315 /*changes=*/{});
10316
10317 InputDeviceInfo info;
10318 controller.populateDeviceInfo(&info);
10319 std::vector<InputDeviceLightInfo> lights = info.getLights();
10320 ASSERT_EQ(1U, lights.size());
10321 ASSERT_EQ(InputDeviceLightType::KEYBOARD_MIC_MUTE, lights[0].type);
10322 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10323}
10324
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010325TEST_F(LightControllerTest, MonoKeyboardBacklight) {
10326 RawLightInfo infoMono = {.id = 1,
10327 .name = "mono_keyboard_backlight",
10328 .maxBrightness = 255,
10329 .flags = InputLightClass::BRIGHTNESS |
10330 InputLightClass::KEYBOARD_BACKLIGHT,
10331 .path = ""};
10332 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10333
10334 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10335 InputDeviceInfo info;
10336 controller.populateDeviceInfo(&info);
10337 std::vector<InputDeviceLightInfo> lights = info.getLights();
10338 ASSERT_EQ(1U, lights.size());
10339 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10340 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010341
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010342 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_BRIGHTNESS));
10343 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_BRIGHTNESS);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010344}
10345
Vaibhav Devmurari16c24192023-05-04 15:20:12 +000010346TEST_F(LightControllerTest, Ignore_MonoLight_WithPreferredBacklightLevels) {
10347 RawLightInfo infoMono = {.id = 1,
10348 .name = "mono_light",
10349 .maxBrightness = 255,
10350 .flags = InputLightClass::BRIGHTNESS,
10351 .path = ""};
10352 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10353 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10354 "0,100,200");
10355
10356 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10357 std::list<NotifyArgs> unused =
10358 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10359 /*changes=*/{});
10360
10361 InputDeviceInfo info;
10362 controller.populateDeviceInfo(&info);
10363 std::vector<InputDeviceLightInfo> lights = info.getLights();
10364 ASSERT_EQ(1U, lights.size());
10365 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10366}
10367
10368TEST_F(LightControllerTest, KeyboardBacklight_WithNoPreferredBacklightLevels) {
10369 RawLightInfo infoMono = {.id = 1,
10370 .name = "mono_keyboard_backlight",
10371 .maxBrightness = 255,
10372 .flags = InputLightClass::BRIGHTNESS |
10373 InputLightClass::KEYBOARD_BACKLIGHT,
10374 .path = ""};
10375 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10376
10377 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10378 std::list<NotifyArgs> unused =
10379 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10380 /*changes=*/{});
10381
10382 InputDeviceInfo info;
10383 controller.populateDeviceInfo(&info);
10384 std::vector<InputDeviceLightInfo> lights = info.getLights();
10385 ASSERT_EQ(1U, lights.size());
10386 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10387}
10388
10389TEST_F(LightControllerTest, KeyboardBacklight_WithPreferredBacklightLevels) {
10390 RawLightInfo infoMono = {.id = 1,
10391 .name = "mono_keyboard_backlight",
10392 .maxBrightness = 255,
10393 .flags = InputLightClass::BRIGHTNESS |
10394 InputLightClass::KEYBOARD_BACKLIGHT,
10395 .path = ""};
10396 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10397 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10398 "0,100,200");
10399
10400 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10401 std::list<NotifyArgs> unused =
10402 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10403 /*changes=*/{});
10404
10405 InputDeviceInfo info;
10406 controller.populateDeviceInfo(&info);
10407 std::vector<InputDeviceLightInfo> lights = info.getLights();
10408 ASSERT_EQ(1U, lights.size());
10409 ASSERT_EQ(3U, lights[0].preferredBrightnessLevels.size());
10410 std::set<BrightnessLevel>::iterator it = lights[0].preferredBrightnessLevels.begin();
10411 ASSERT_EQ(BrightnessLevel(0), *it);
10412 std::advance(it, 1);
10413 ASSERT_EQ(BrightnessLevel(100), *it);
10414 std::advance(it, 1);
10415 ASSERT_EQ(BrightnessLevel(200), *it);
10416}
10417
10418TEST_F(LightControllerTest, KeyboardBacklight_WithWrongPreferredBacklightLevels) {
10419 RawLightInfo infoMono = {.id = 1,
10420 .name = "mono_keyboard_backlight",
10421 .maxBrightness = 255,
10422 .flags = InputLightClass::BRIGHTNESS |
10423 InputLightClass::KEYBOARD_BACKLIGHT,
10424 .path = ""};
10425 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10426 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10427 "0,100,200,300,400,500");
10428
10429 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10430 std::list<NotifyArgs> unused =
10431 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10432 /*changes=*/{});
10433
10434 InputDeviceInfo info;
10435 controller.populateDeviceInfo(&info);
10436 std::vector<InputDeviceLightInfo> lights = info.getLights();
10437 ASSERT_EQ(1U, lights.size());
10438 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10439}
10440
Chris Yee2b1e5c2021-03-10 22:45:12 -080010441TEST_F(LightControllerTest, RGBLight) {
10442 RawLightInfo infoRed = {.id = 1,
10443 .name = "red",
10444 .maxBrightness = 255,
10445 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED,
10446 .path = ""};
10447 RawLightInfo infoGreen = {.id = 2,
10448 .name = "green",
10449 .maxBrightness = 255,
10450 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN,
10451 .path = ""};
10452 RawLightInfo infoBlue = {.id = 3,
10453 .name = "blue",
10454 .maxBrightness = 255,
10455 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE,
10456 .path = ""};
10457 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10458 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10459 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10460
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010461 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010462 InputDeviceInfo info;
10463 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010464 std::vector<InputDeviceLightInfo> lights = info.getLights();
10465 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010466 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10467 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10468 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10469
10470 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10471 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10472}
10473
10474TEST_F(LightControllerTest, CorrectRGBKeyboardBacklight) {
10475 RawLightInfo infoRed = {.id = 1,
10476 .name = "red_keyboard_backlight",
10477 .maxBrightness = 255,
10478 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED |
10479 InputLightClass::KEYBOARD_BACKLIGHT,
10480 .path = ""};
10481 RawLightInfo infoGreen = {.id = 2,
10482 .name = "green_keyboard_backlight",
10483 .maxBrightness = 255,
10484 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN |
10485 InputLightClass::KEYBOARD_BACKLIGHT,
10486 .path = ""};
10487 RawLightInfo infoBlue = {.id = 3,
10488 .name = "blue_keyboard_backlight",
10489 .maxBrightness = 255,
10490 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE |
10491 InputLightClass::KEYBOARD_BACKLIGHT,
10492 .path = ""};
10493 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10494 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10495 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10496
10497 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10498 InputDeviceInfo info;
10499 controller.populateDeviceInfo(&info);
10500 std::vector<InputDeviceLightInfo> lights = info.getLights();
10501 ASSERT_EQ(1U, lights.size());
10502 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10503 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10504 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10505
10506 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10507 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10508}
10509
10510TEST_F(LightControllerTest, IncorrectRGBKeyboardBacklight) {
10511 RawLightInfo infoRed = {.id = 1,
10512 .name = "red",
10513 .maxBrightness = 255,
10514 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED,
10515 .path = ""};
10516 RawLightInfo infoGreen = {.id = 2,
10517 .name = "green",
10518 .maxBrightness = 255,
10519 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN,
10520 .path = ""};
10521 RawLightInfo infoBlue = {.id = 3,
10522 .name = "blue",
10523 .maxBrightness = 255,
10524 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE,
10525 .path = ""};
10526 RawLightInfo infoGlobal = {.id = 3,
10527 .name = "global_keyboard_backlight",
10528 .maxBrightness = 255,
10529 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GLOBAL |
10530 InputLightClass::KEYBOARD_BACKLIGHT,
10531 .path = ""};
10532 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10533 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10534 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10535 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoGlobal));
10536
10537 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10538 InputDeviceInfo info;
10539 controller.populateDeviceInfo(&info);
10540 std::vector<InputDeviceLightInfo> lights = info.getLights();
10541 ASSERT_EQ(1U, lights.size());
10542 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10543 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10544 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010545
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010546 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10547 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010548}
10549
10550TEST_F(LightControllerTest, MultiColorRGBLight) {
10551 RawLightInfo infoColor = {.id = 1,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010552 .name = "multi_color",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010553 .maxBrightness = 255,
10554 .flags = InputLightClass::BRIGHTNESS |
10555 InputLightClass::MULTI_INTENSITY |
10556 InputLightClass::MULTI_INDEX,
10557 .path = ""};
10558
10559 mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
10560
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010561 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010562 InputDeviceInfo info;
10563 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010564 std::vector<InputDeviceLightInfo> lights = info.getLights();
10565 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010566 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10567 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10568 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10569
10570 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10571 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10572}
10573
10574TEST_F(LightControllerTest, MultiColorRGBKeyboardBacklight) {
10575 RawLightInfo infoColor = {.id = 1,
10576 .name = "multi_color_keyboard_backlight",
10577 .maxBrightness = 255,
10578 .flags = InputLightClass::BRIGHTNESS |
10579 InputLightClass::MULTI_INTENSITY |
10580 InputLightClass::MULTI_INDEX |
10581 InputLightClass::KEYBOARD_BACKLIGHT,
10582 .path = ""};
10583
10584 mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
10585
10586 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10587 InputDeviceInfo info;
10588 controller.populateDeviceInfo(&info);
10589 std::vector<InputDeviceLightInfo> lights = info.getLights();
10590 ASSERT_EQ(1U, lights.size());
10591 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10592 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10593 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010594
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010595 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10596 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010597}
10598
10599TEST_F(LightControllerTest, PlayerIdLight) {
10600 RawLightInfo info1 = {.id = 1,
10601 .name = "player1",
10602 .maxBrightness = 255,
10603 .flags = InputLightClass::BRIGHTNESS,
10604 .path = ""};
10605 RawLightInfo info2 = {.id = 2,
10606 .name = "player2",
10607 .maxBrightness = 255,
10608 .flags = InputLightClass::BRIGHTNESS,
10609 .path = ""};
10610 RawLightInfo info3 = {.id = 3,
10611 .name = "player3",
10612 .maxBrightness = 255,
10613 .flags = InputLightClass::BRIGHTNESS,
10614 .path = ""};
10615 RawLightInfo info4 = {.id = 4,
10616 .name = "player4",
10617 .maxBrightness = 255,
10618 .flags = InputLightClass::BRIGHTNESS,
10619 .path = ""};
10620 mFakeEventHub->addRawLightInfo(info1.id, std::move(info1));
10621 mFakeEventHub->addRawLightInfo(info2.id, std::move(info2));
10622 mFakeEventHub->addRawLightInfo(info3.id, std::move(info3));
10623 mFakeEventHub->addRawLightInfo(info4.id, std::move(info4));
10624
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010625 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010626 InputDeviceInfo info;
10627 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010628 std::vector<InputDeviceLightInfo> lights = info.getLights();
10629 ASSERT_EQ(1U, lights.size());
10630 ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010631 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10632 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010633
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010634 ASSERT_FALSE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10635 ASSERT_TRUE(controller.setLightPlayerId(lights[0].id, LIGHT_PLAYER_ID));
10636 ASSERT_EQ(controller.getLightPlayerId(lights[0].id).value_or(-1), LIGHT_PLAYER_ID);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010637}
10638
Michael Wrightd02c5b62014-02-10 15:10:22 -080010639} // namespace android