blob: 93fae9b4acc858fd41a63bb43ce5584a147abf38 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Dominik Laskowski2f01d772022-03-23 16:01:29 -070017#include <cinttypes>
18#include <memory>
Harry Cuttsf13161a2023-03-08 14:15:49 +000019#include <optional>
Dominik Laskowski2f01d772022-03-23 16:01:29 -070020
Prabir Pradhan2770d242019-09-02 18:07:11 -070021#include <CursorInputMapper.h>
22#include <InputDevice.h>
23#include <InputMapper.h>
24#include <InputReader.h>
Prabir Pradhan1aed8582019-12-30 11:46:51 -080025#include <InputReaderBase.h>
26#include <InputReaderFactory.h>
Arthur Hung6d5b4b22022-01-21 07:21:10 +000027#include <JoystickInputMapper.h>
Prabir Pradhan2770d242019-09-02 18:07:11 -070028#include <KeyboardInputMapper.h>
29#include <MultiTouchInputMapper.h>
Prabir Pradhan018faea2024-05-08 21:52:54 +000030#include <NotifyArgsBuilders.h>
Chris Ye1dd2e5c2021-04-04 23:12:41 -070031#include <PeripheralController.h>
Chris Yef59a2f42020-10-16 12:55:26 -070032#include <SensorInputMapper.h>
Prabir Pradhan2770d242019-09-02 18:07:11 -070033#include <SingleTouchInputMapper.h>
34#include <SwitchInputMapper.h>
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000035#include <TestEventMatchers.h>
Prabir Pradhan2770d242019-09-02 18:07:11 -070036#include <TestInputListener.h>
37#include <TouchInputMapper.h>
Prabir Pradhan1aed8582019-12-30 11:46:51 -080038#include <UinputDevice.h>
Chris Ye87143712020-11-10 05:05:58 +000039#include <VibratorInputMapper.h>
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070040#include <android-base/thread_annotations.h>
Byoungho Jungda10dd32023-10-06 17:03:45 +090041#include <com_android_input_flags.h>
Michael Wrighta9cf4192022-12-01 23:46:39 +000042#include <ftl/enum.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080043#include <gtest/gtest.h>
Michael Wrighta9cf4192022-12-01 23:46:39 +000044#include <ui/Rotation.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080045
Siarhei Vishniakou21e96e62022-10-27 10:23:37 -070046#include <thread>
Harry Cuttsa5b71292022-11-28 12:56:17 +000047#include "FakeEventHub.h"
Harry Cutts6b5fbc52022-11-28 16:37:43 +000048#include "FakeInputReaderPolicy.h"
Harry Cuttse6512e12022-11-28 18:44:01 +000049#include "InputMapperTest.h"
Harry Cutts144ff542022-11-28 17:41:06 +000050#include "InstrumentedInputReader.h"
Harry Cuttsa5b71292022-11-28 12:56:17 +000051#include "TestConstants.h"
Michael Wrightdde67b82020-10-27 16:09:22 +000052#include "input/DisplayViewport.h"
53#include "input/Input.h"
Michael Wright17db18e2020-06-26 20:51:44 +010054
Michael Wrightd02c5b62014-02-10 15:10:22 -080055namespace android {
56
Dominik Laskowski2f01d772022-03-23 16:01:29 -070057using namespace ftl::flag_operators;
Prabir Pradhan739dca42022-09-09 20:12:01 +000058using testing::AllOf;
Biswarup Palb08159b2024-08-22 09:12:19 +000059using testing::VariantWith;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070060using std::chrono_literals::operator""ms;
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -080061using std::chrono_literals::operator""s;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070062
Michael Wrightd02c5b62014-02-10 15:10:22 -080063// Arbitrary display properties.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070064static constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhanc13ff082022-09-08 22:03:30 +000065static const std::string DISPLAY_UNIQUE_ID = "local:1";
Linnan Li13bf76a2024-05-05 19:18:02 +080066static constexpr ui::LogicalDisplayId SECONDARY_DISPLAY_ID =
67 ui::LogicalDisplayId{DISPLAY_ID.val() + 1};
arthurhungcc7f9802020-04-30 17:55:40 +080068static constexpr int32_t DISPLAY_WIDTH = 480;
69static constexpr int32_t DISPLAY_HEIGHT = 800;
Linnan Li13bf76a2024-05-05 19:18:02 +080070static constexpr ui::LogicalDisplayId VIRTUAL_DISPLAY_ID = ui::LogicalDisplayId{1};
arthurhungcc7f9802020-04-30 17:55:40 +080071static constexpr int32_t VIRTUAL_DISPLAY_WIDTH = 400;
72static constexpr int32_t VIRTUAL_DISPLAY_HEIGHT = 500;
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -070073static const char* VIRTUAL_DISPLAY_UNIQUE_ID = "virtual:1";
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -070074static constexpr std::optional<uint8_t> NO_PORT = std::nullopt; // no physical port is specified
Michael Wrightd02c5b62014-02-10 15:10:22 -080075
arthurhungcc7f9802020-04-30 17:55:40 +080076static constexpr int32_t FIRST_SLOT = 0;
77static constexpr int32_t SECOND_SLOT = 1;
78static constexpr int32_t THIRD_SLOT = 2;
79static constexpr int32_t INVALID_TRACKING_ID = -1;
80static constexpr int32_t FIRST_TRACKING_ID = 0;
81static constexpr int32_t SECOND_TRACKING_ID = 1;
82static constexpr int32_t THIRD_TRACKING_ID = 2;
Chris Ye3fdbfef2021-01-06 18:45:18 -080083static constexpr int32_t LIGHT_BRIGHTNESS = 0x55000000;
84static constexpr int32_t LIGHT_COLOR = 0x7F448866;
85static constexpr int32_t LIGHT_PLAYER_ID = 2;
arthurhungcc7f9802020-04-30 17:55:40 +080086
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -080087static constexpr int32_t ACTION_POINTER_0_DOWN =
88 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
89static constexpr int32_t ACTION_POINTER_0_UP =
90 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
91static constexpr int32_t ACTION_POINTER_1_DOWN =
92 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
93static constexpr int32_t ACTION_POINTER_1_UP =
94 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
95
Prabir Pradhanb08a0e82023-09-14 22:28:32 +000096static constexpr uint32_t STYLUS_FUSION_SOURCE =
97 AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_BLUETOOTH_STYLUS;
98
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +000099// Minimum timestamp separation between subsequent input events from a Bluetooth device.
100static constexpr nsecs_t MIN_BLUETOOTH_TIMESTAMP_DELTA = ms2ns(4);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +0000101
Byoungho Jungda10dd32023-10-06 17:03:45 +0900102namespace input_flags = com::android::input::flags;
103
Michael Wrightd02c5b62014-02-10 15:10:22 -0800104template<typename T>
105static inline T min(T a, T b) {
106 return a < b ? a : b;
107}
108
109static inline float avg(float x, float y) {
110 return (x + y) / 2;
111}
112
Chris Ye3fdbfef2021-01-06 18:45:18 -0800113// Mapping for light color name and the light color
114const std::unordered_map<std::string, LightColor> LIGHT_COLORS = {{"red", LightColor::RED},
115 {"green", LightColor::GREEN},
116 {"blue", LightColor::BLUE}};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800117
Michael Wrighta9cf4192022-12-01 23:46:39 +0000118static ui::Rotation getInverseRotation(ui::Rotation orientation) {
Prabir Pradhanc14266f2021-05-12 15:56:24 -0700119 switch (orientation) {
Michael Wrighta9cf4192022-12-01 23:46:39 +0000120 case ui::ROTATION_90:
121 return ui::ROTATION_270;
122 case ui::ROTATION_270:
123 return ui::ROTATION_90;
Prabir Pradhanc14266f2021-05-12 15:56:24 -0700124 default:
125 return orientation;
126 }
127}
128
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800129static void assertAxisResolution(MultiTouchInputMapper& mapper, int axis, float resolution) {
130 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +0000131 mapper.populateDeviceInfo(info);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800132
133 const InputDeviceInfo::MotionRange* motionRange =
134 info.getMotionRange(axis, AINPUT_SOURCE_TOUCHSCREEN);
135 ASSERT_NEAR(motionRange->resolution, resolution, EPSILON);
136}
137
138static void assertAxisNotPresent(MultiTouchInputMapper& mapper, int axis) {
139 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +0000140 mapper.populateDeviceInfo(info);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800141
142 const InputDeviceInfo::MotionRange* motionRange =
143 info.getMotionRange(axis, AINPUT_SOURCE_TOUCHSCREEN);
144 ASSERT_EQ(nullptr, motionRange);
145}
146
Siarhei Vishniakou21e96e62022-10-27 10:23:37 -0700147[[maybe_unused]] static void dumpReader(InputReader& reader) {
148 std::string dump;
149 reader.dump(dump);
150 std::istringstream iss(dump);
151 for (std::string line; std::getline(iss, line);) {
152 ALOGE("%s", line.c_str());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -0800153 std::this_thread::sleep_for(1ms);
Siarhei Vishniakou21e96e62022-10-27 10:23:37 -0700154 }
155}
156
Michael Wrightd02c5b62014-02-10 15:10:22 -0800157// --- FakeInputMapper ---
158
159class FakeInputMapper : public InputMapper {
160 uint32_t mSources;
161 int32_t mKeyboardType;
162 int32_t mMetaState;
163 KeyedVector<int32_t, int32_t> mKeyCodeStates;
164 KeyedVector<int32_t, int32_t> mScanCodeStates;
165 KeyedVector<int32_t, int32_t> mSwitchStates;
Philip Junker4af3b3d2021-12-14 10:36:55 +0100166 // fake mapping which would normally come from keyCharacterMap
167 std::unordered_map<int32_t, int32_t> mKeyCodeMapping;
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800168 std::vector<int32_t> mSupportedKeyCodes;
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700169 std::list<NotifyArgs> mProcessResult;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800170
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700171 std::mutex mLock;
172 std::condition_variable mStateChangedCondition;
173 bool mConfigureWasCalled GUARDED_BY(mLock);
174 bool mResetWasCalled GUARDED_BY(mLock);
175 bool mProcessWasCalled GUARDED_BY(mLock);
176 RawEvent mLastEvent GUARDED_BY(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800177
Arthur Hungc23540e2018-11-29 20:42:11 +0800178 std::optional<DisplayViewport> mViewport;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800179public:
Arpit Singh8e6fb252023-04-06 11:49:17 +0000180 FakeInputMapper(InputDeviceContext& deviceContext, const InputReaderConfiguration& readerConfig,
181 uint32_t sources)
182 : InputMapper(deviceContext, readerConfig),
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800183 mSources(sources),
184 mKeyboardType(AINPUT_KEYBOARD_TYPE_NONE),
Michael Wrightd02c5b62014-02-10 15:10:22 -0800185 mMetaState(0),
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800186 mConfigureWasCalled(false),
187 mResetWasCalled(false),
188 mProcessWasCalled(false) {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800189
Chris Yea52ade12020-08-27 16:49:20 -0700190 virtual ~FakeInputMapper() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800191
192 void setKeyboardType(int32_t keyboardType) {
193 mKeyboardType = keyboardType;
194 }
195
196 void setMetaState(int32_t metaState) {
197 mMetaState = metaState;
198 }
199
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700200 // Sets the return value for the `process` call.
201 void setProcessResult(std::list<NotifyArgs> notifyArgs) {
202 mProcessResult.clear();
203 for (auto notifyArg : notifyArgs) {
204 mProcessResult.push_back(notifyArg);
205 }
206 }
207
Michael Wrightd02c5b62014-02-10 15:10:22 -0800208 void assertConfigureWasCalled() {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700209 std::unique_lock<std::mutex> lock(mLock);
210 base::ScopedLockAssertion assumeLocked(mLock);
211 const bool configureCalled =
212 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
213 return mConfigureWasCalled;
214 });
215 if (!configureCalled) {
216 FAIL() << "Expected configure() to have been called.";
217 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800218 mConfigureWasCalled = false;
219 }
220
221 void assertResetWasCalled() {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700222 std::unique_lock<std::mutex> lock(mLock);
223 base::ScopedLockAssertion assumeLocked(mLock);
224 const bool resetCalled =
225 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
226 return mResetWasCalled;
227 });
228 if (!resetCalled) {
229 FAIL() << "Expected reset() to have been called.";
230 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800231 mResetWasCalled = false;
232 }
233
Prabir Pradhanf8d9e442023-12-06 22:06:13 +0000234 void assertResetWasNotCalled() {
235 std::scoped_lock lock(mLock);
236 ASSERT_FALSE(mResetWasCalled) << "Expected reset to not have been called.";
237 }
238
Yi Kong9b14ac62018-07-17 13:48:38 -0700239 void assertProcessWasCalled(RawEvent* outLastEvent = nullptr) {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700240 std::unique_lock<std::mutex> lock(mLock);
241 base::ScopedLockAssertion assumeLocked(mLock);
242 const bool processCalled =
243 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
244 return mProcessWasCalled;
245 });
246 if (!processCalled) {
247 FAIL() << "Expected process() to have been called.";
248 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800249 if (outLastEvent) {
250 *outLastEvent = mLastEvent;
251 }
252 mProcessWasCalled = false;
253 }
254
Prabir Pradhanf8d9e442023-12-06 22:06:13 +0000255 void assertProcessWasNotCalled() {
256 std::scoped_lock lock(mLock);
257 ASSERT_FALSE(mProcessWasCalled) << "Expected process to not have been called.";
258 }
259
Michael Wrightd02c5b62014-02-10 15:10:22 -0800260 void setKeyCodeState(int32_t keyCode, int32_t state) {
261 mKeyCodeStates.replaceValueFor(keyCode, state);
262 }
263
264 void setScanCodeState(int32_t scanCode, int32_t state) {
265 mScanCodeStates.replaceValueFor(scanCode, state);
266 }
267
268 void setSwitchState(int32_t switchCode, int32_t state) {
269 mSwitchStates.replaceValueFor(switchCode, state);
270 }
271
272 void addSupportedKeyCode(int32_t keyCode) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800273 mSupportedKeyCodes.push_back(keyCode);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800274 }
275
Philip Junker4af3b3d2021-12-14 10:36:55 +0100276 void addKeyCodeMapping(int32_t fromKeyCode, int32_t toKeyCode) {
277 mKeyCodeMapping.insert_or_assign(fromKeyCode, toKeyCode);
278 }
279
Michael Wrightd02c5b62014-02-10 15:10:22 -0800280private:
Philip Junker4af3b3d2021-12-14 10:36:55 +0100281 uint32_t getSources() const override { return mSources; }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800282
Harry Cuttsd02ea102023-03-17 18:21:30 +0000283 void populateDeviceInfo(InputDeviceInfo& deviceInfo) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800284 InputMapper::populateDeviceInfo(deviceInfo);
285
286 if (mKeyboardType != AINPUT_KEYBOARD_TYPE_NONE) {
Harry Cuttsd02ea102023-03-17 18:21:30 +0000287 deviceInfo.setKeyboardType(mKeyboardType);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800288 }
289 }
290
Arpit Singhed6c3de2023-04-05 19:24:37 +0000291 std::list<NotifyArgs> reconfigure(nsecs_t, const InputReaderConfiguration& config,
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000292 ConfigurationChanges changes) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700293 std::scoped_lock<std::mutex> lock(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800294 mConfigureWasCalled = true;
Arthur Hungc23540e2018-11-29 20:42:11 +0800295
296 // Find the associated viewport if exist.
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800297 const std::optional<uint8_t> displayPort = getDeviceContext().getAssociatedDisplayPort();
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000298 if (displayPort && changes.test(InputReaderConfiguration::Change::DISPLAY_INFO)) {
Arpit Singhed6c3de2023-04-05 19:24:37 +0000299 mViewport = config.getDisplayViewportByPort(*displayPort);
Arthur Hungc23540e2018-11-29 20:42:11 +0800300 }
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700301
302 mStateChangedCondition.notify_all();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700303 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800304 }
305
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700306 std::list<NotifyArgs> reset(nsecs_t) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700307 std::scoped_lock<std::mutex> lock(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800308 mResetWasCalled = true;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700309 mStateChangedCondition.notify_all();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700310 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800311 }
312
Harry Cuttsa32a1192024-06-04 15:10:31 +0000313 std::list<NotifyArgs> process(const RawEvent& rawEvent) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700314 std::scoped_lock<std::mutex> lock(mLock);
Harry Cuttsa32a1192024-06-04 15:10:31 +0000315 mLastEvent = rawEvent;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800316 mProcessWasCalled = true;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700317 mStateChangedCondition.notify_all();
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700318 return mProcessResult;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800319 }
320
Chris Yea52ade12020-08-27 16:49:20 -0700321 int32_t getKeyCodeState(uint32_t, int32_t keyCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800322 ssize_t index = mKeyCodeStates.indexOfKey(keyCode);
323 return index >= 0 ? mKeyCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
324 }
325
Philip Junker4af3b3d2021-12-14 10:36:55 +0100326 int32_t getKeyCodeForKeyLocation(int32_t locationKeyCode) const override {
327 auto it = mKeyCodeMapping.find(locationKeyCode);
328 return it != mKeyCodeMapping.end() ? it->second : locationKeyCode;
329 }
330
Chris Yea52ade12020-08-27 16:49:20 -0700331 int32_t getScanCodeState(uint32_t, int32_t scanCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800332 ssize_t index = mScanCodeStates.indexOfKey(scanCode);
333 return index >= 0 ? mScanCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
334 }
335
Chris Yea52ade12020-08-27 16:49:20 -0700336 int32_t getSwitchState(uint32_t, int32_t switchCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800337 ssize_t index = mSwitchStates.indexOfKey(switchCode);
338 return index >= 0 ? mSwitchStates.valueAt(index) : AKEY_STATE_UNKNOWN;
339 }
340
Chris Yea52ade12020-08-27 16:49:20 -0700341 // Return true if the device has non-empty key layout.
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700342 bool markSupportedKeyCodes(uint32_t, const std::vector<int32_t>& keyCodes,
Chris Yea52ade12020-08-27 16:49:20 -0700343 uint8_t* outFlags) override {
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700344 for (size_t i = 0; i < keyCodes.size(); i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800345 for (size_t j = 0; j < mSupportedKeyCodes.size(); j++) {
346 if (keyCodes[i] == mSupportedKeyCodes[j]) {
347 outFlags[i] = 1;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800348 }
349 }
350 }
Chris Yea52ade12020-08-27 16:49:20 -0700351 bool result = mSupportedKeyCodes.size() > 0;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800352 return result;
353 }
354
355 virtual int32_t getMetaState() {
356 return mMetaState;
357 }
358
359 virtual void fadePointer() {
360 }
Arthur Hungc23540e2018-11-29 20:42:11 +0800361
Linnan Li13bf76a2024-05-05 19:18:02 +0800362 virtual std::optional<ui::LogicalDisplayId> getAssociatedDisplay() {
Arthur Hungc23540e2018-11-29 20:42:11 +0800363 if (mViewport) {
364 return std::make_optional(mViewport->displayId);
365 }
366 return std::nullopt;
367 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800368};
369
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700370// --- InputReaderPolicyTest ---
371class InputReaderPolicyTest : public testing::Test {
Siarhei Vishniakoucd7ac1e2018-10-15 13:39:50 -0700372protected:
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700373 sp<FakeInputReaderPolicy> mFakePolicy;
374
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700375 void SetUp() override { mFakePolicy = sp<FakeInputReaderPolicy>::make(); }
Chris Yea52ade12020-08-27 16:49:20 -0700376 void TearDown() override { mFakePolicy.clear(); }
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700377};
378
379/**
380 * Check that empty set of viewports is an acceptable configuration.
381 * Also try to get internal viewport two different ways - by type and by uniqueId.
382 *
383 * There will be confusion if two viewports with empty uniqueId and identical type are present.
384 * Such configuration is not currently allowed.
385 */
386TEST_F(InputReaderPolicyTest, Viewports_GetCleared) {
Siarhei Vishniakoucd7ac1e2018-10-15 13:39:50 -0700387 static const std::string uniqueId = "local:0";
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700388
389 // We didn't add any viewports yet, so there shouldn't be any.
390 std::optional<DisplayViewport> internalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100391 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700392 ASSERT_FALSE(internalViewport);
393
394 // Add an internal viewport, then clear it
Michael Wrighta9cf4192022-12-01 23:46:39 +0000395 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000396 /*isActive=*/true, uniqueId, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700397
398 // Check matching by uniqueId
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700399 internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700400 ASSERT_TRUE(internalViewport);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100401 ASSERT_EQ(ViewportType::INTERNAL, internalViewport->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700402
403 // Check matching by viewport type
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100404 internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700405 ASSERT_TRUE(internalViewport);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700406 ASSERT_EQ(uniqueId, internalViewport->uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700407
408 mFakePolicy->clearViewports();
409 // Make sure nothing is found after clear
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700410 internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700411 ASSERT_FALSE(internalViewport);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100412 internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700413 ASSERT_FALSE(internalViewport);
414}
415
416TEST_F(InputReaderPolicyTest, Viewports_GetByType) {
417 const std::string internalUniqueId = "local:0";
418 const std::string externalUniqueId = "local:1";
419 const std::string virtualUniqueId1 = "virtual:2";
420 const std::string virtualUniqueId2 = "virtual:3";
Linnan Li13bf76a2024-05-05 19:18:02 +0800421 constexpr ui::LogicalDisplayId virtualDisplayId1 = ui::LogicalDisplayId{2};
422 constexpr ui::LogicalDisplayId virtualDisplayId2 = ui::LogicalDisplayId{3};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700423
424 // Add an internal viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000425 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000426 /*isActive=*/true, internalUniqueId, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000427 ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700428 // Add an external viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000429 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000430 /*isActive=*/true, externalUniqueId, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000431 ViewportType::EXTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700432 // Add an virtual viewport
433 mFakePolicy->addDisplayViewport(virtualDisplayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000434 ui::ROTATION_0, /*isActive=*/true, virtualUniqueId1, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000435 ViewportType::VIRTUAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700436 // Add another virtual viewport
437 mFakePolicy->addDisplayViewport(virtualDisplayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000438 ui::ROTATION_0, /*isActive=*/true, virtualUniqueId2, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000439 ViewportType::VIRTUAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700440
441 // Check matching by type for internal
442 std::optional<DisplayViewport> internalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100443 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700444 ASSERT_TRUE(internalViewport);
445 ASSERT_EQ(internalUniqueId, internalViewport->uniqueId);
446
447 // Check matching by type for external
448 std::optional<DisplayViewport> externalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100449 mFakePolicy->getDisplayViewportByType(ViewportType::EXTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700450 ASSERT_TRUE(externalViewport);
451 ASSERT_EQ(externalUniqueId, externalViewport->uniqueId);
452
453 // Check matching by uniqueId for virtual viewport #1
454 std::optional<DisplayViewport> virtualViewport1 =
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700455 mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId1);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700456 ASSERT_TRUE(virtualViewport1);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100457 ASSERT_EQ(ViewportType::VIRTUAL, virtualViewport1->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700458 ASSERT_EQ(virtualUniqueId1, virtualViewport1->uniqueId);
459 ASSERT_EQ(virtualDisplayId1, virtualViewport1->displayId);
460
461 // Check matching by uniqueId for virtual viewport #2
462 std::optional<DisplayViewport> virtualViewport2 =
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700463 mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId2);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700464 ASSERT_TRUE(virtualViewport2);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100465 ASSERT_EQ(ViewportType::VIRTUAL, virtualViewport2->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700466 ASSERT_EQ(virtualUniqueId2, virtualViewport2->uniqueId);
467 ASSERT_EQ(virtualDisplayId2, virtualViewport2->displayId);
468}
469
470
471/**
472 * We can have 2 viewports of the same kind. We can distinguish them by uniqueId, and confirm
473 * that lookup works by checking display id.
474 * Check that 2 viewports of each kind is possible, for all existing viewport types.
475 */
476TEST_F(InputReaderPolicyTest, Viewports_TwoOfSameType) {
477 const std::string uniqueId1 = "uniqueId1";
478 const std::string uniqueId2 = "uniqueId2";
Linnan Li13bf76a2024-05-05 19:18:02 +0800479 constexpr ui::LogicalDisplayId displayId1 = ui::LogicalDisplayId{2};
480 constexpr ui::LogicalDisplayId displayId2 = ui::LogicalDisplayId{3};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700481
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100482 std::vector<ViewportType> types = {ViewportType::INTERNAL, ViewportType::EXTERNAL,
483 ViewportType::VIRTUAL};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700484 for (const ViewportType& type : types) {
485 mFakePolicy->clearViewports();
486 // Add a viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000487 mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000488 /*isActive=*/true, uniqueId1, NO_PORT, type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700489 // Add another viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000490 mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000491 /*isActive=*/true, uniqueId2, NO_PORT, type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700492
493 // Check that correct display viewport was returned by comparing the display IDs.
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700494 std::optional<DisplayViewport> viewport1 =
495 mFakePolicy->getDisplayViewportByUniqueId(uniqueId1);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700496 ASSERT_TRUE(viewport1);
497 ASSERT_EQ(displayId1, viewport1->displayId);
498 ASSERT_EQ(type, viewport1->type);
499
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700500 std::optional<DisplayViewport> viewport2 =
501 mFakePolicy->getDisplayViewportByUniqueId(uniqueId2);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700502 ASSERT_TRUE(viewport2);
503 ASSERT_EQ(displayId2, viewport2->displayId);
504 ASSERT_EQ(type, viewport2->type);
505
506 // When there are multiple viewports of the same kind, and uniqueId is not specified
507 // in the call to getDisplayViewport, then that situation is not supported.
508 // The viewports can be stored in any order, so we cannot rely on the order, since that
509 // is just implementation detail.
510 // However, we can check that it still returns *a* viewport, we just cannot assert
511 // which one specifically is returned.
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700512 std::optional<DisplayViewport> someViewport = mFakePolicy->getDisplayViewportByType(type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700513 ASSERT_TRUE(someViewport);
514 }
515}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800516
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700517/**
Michael Wrightdde67b82020-10-27 16:09:22 +0000518 * When we have multiple internal displays make sure we always return the default display when
519 * querying by type.
520 */
521TEST_F(InputReaderPolicyTest, Viewports_ByTypeReturnsDefaultForInternal) {
522 const std::string uniqueId1 = "uniqueId1";
523 const std::string uniqueId2 = "uniqueId2";
Linnan Li13bf76a2024-05-05 19:18:02 +0800524 constexpr ui::LogicalDisplayId nonDefaultDisplayId = ui::LogicalDisplayId{2};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700525 ASSERT_NE(nonDefaultDisplayId, ui::LogicalDisplayId::DEFAULT)
526 << "Test display ID should not be ui::LogicalDisplayId::DEFAULT ";
Michael Wrightdde67b82020-10-27 16:09:22 +0000527
528 // Add the default display first and ensure it gets returned.
529 mFakePolicy->clearViewports();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700530 mFakePolicy->addDisplayViewport(ui::LogicalDisplayId::DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000531 ui::ROTATION_0, /*isActive=*/true, uniqueId1, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000532 ViewportType::INTERNAL);
533 mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000534 ui::ROTATION_0, /*isActive=*/true, uniqueId2, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000535 ViewportType::INTERNAL);
536
537 std::optional<DisplayViewport> viewport =
538 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
539 ASSERT_TRUE(viewport);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700540 ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, viewport->displayId);
Michael Wrightdde67b82020-10-27 16:09:22 +0000541 ASSERT_EQ(ViewportType::INTERNAL, viewport->type);
542
543 // Add the default display second to make sure order doesn't matter.
544 mFakePolicy->clearViewports();
545 mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000546 ui::ROTATION_0, /*isActive=*/true, uniqueId2, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000547 ViewportType::INTERNAL);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700548 mFakePolicy->addDisplayViewport(ui::LogicalDisplayId::DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000549 ui::ROTATION_0, /*isActive=*/true, uniqueId1, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000550 ViewportType::INTERNAL);
551
552 viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
553 ASSERT_TRUE(viewport);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700554 ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, viewport->displayId);
Michael Wrightdde67b82020-10-27 16:09:22 +0000555 ASSERT_EQ(ViewportType::INTERNAL, viewport->type);
556}
557
558/**
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700559 * Check getDisplayViewportByPort
560 */
561TEST_F(InputReaderPolicyTest, Viewports_GetByPort) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100562 constexpr ViewportType type = ViewportType::EXTERNAL;
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700563 const std::string uniqueId1 = "uniqueId1";
564 const std::string uniqueId2 = "uniqueId2";
Linnan Li13bf76a2024-05-05 19:18:02 +0800565 constexpr ui::LogicalDisplayId displayId1 = ui::LogicalDisplayId{1};
566 constexpr ui::LogicalDisplayId displayId2 = ui::LogicalDisplayId{2};
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700567 const uint8_t hdmi1 = 0;
568 const uint8_t hdmi2 = 1;
569 const uint8_t hdmi3 = 2;
570
571 mFakePolicy->clearViewports();
572 // Add a viewport that's associated with some display port that's not of interest.
Michael Wrighta9cf4192022-12-01 23:46:39 +0000573 mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000574 /*isActive=*/true, uniqueId1, hdmi3, type);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700575 // Add another viewport, connected to HDMI1 port
Michael Wrighta9cf4192022-12-01 23:46:39 +0000576 mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000577 /*isActive=*/true, uniqueId2, hdmi1, type);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700578
579 // Check that correct display viewport was returned by comparing the display ports.
580 std::optional<DisplayViewport> hdmi1Viewport = mFakePolicy->getDisplayViewportByPort(hdmi1);
581 ASSERT_TRUE(hdmi1Viewport);
582 ASSERT_EQ(displayId2, hdmi1Viewport->displayId);
583 ASSERT_EQ(uniqueId2, hdmi1Viewport->uniqueId);
584
585 // Check that we can still get the same viewport using the uniqueId
586 hdmi1Viewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId2);
587 ASSERT_TRUE(hdmi1Viewport);
588 ASSERT_EQ(displayId2, hdmi1Viewport->displayId);
589 ASSERT_EQ(uniqueId2, hdmi1Viewport->uniqueId);
590 ASSERT_EQ(type, hdmi1Viewport->type);
591
592 // Check that we cannot find a port with "HDMI2", because we never added one
593 std::optional<DisplayViewport> hdmi2Viewport = mFakePolicy->getDisplayViewportByPort(hdmi2);
594 ASSERT_FALSE(hdmi2Viewport);
595}
596
Michael Wrightd02c5b62014-02-10 15:10:22 -0800597// --- InputReaderTest ---
598
599class InputReaderTest : public testing::Test {
600protected:
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700601 std::unique_ptr<TestInputListener> mFakeListener;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800602 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou3bc7e092019-07-24 17:43:30 -0700603 std::shared_ptr<FakeEventHub> mFakeEventHub;
Prabir Pradhan28efc192019-11-05 01:10:04 +0000604 std::unique_ptr<InstrumentedInputReader> mReader;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800605
Chris Yea52ade12020-08-27 16:49:20 -0700606 void SetUp() override {
Siarhei Vishniakou3bc7e092019-07-24 17:43:30 -0700607 mFakeEventHub = std::make_unique<FakeEventHub>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700608 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700609 mFakeListener = std::make_unique<TestInputListener>();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800610
Prabir Pradhan28efc192019-11-05 01:10:04 +0000611 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700612 *mFakeListener);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800613 }
614
Chris Yea52ade12020-08-27 16:49:20 -0700615 void TearDown() override {
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700616 mFakeListener.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800617 mFakePolicy.clear();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800618 }
619
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700620 void addDevice(int32_t eventHubId, const std::string& name,
621 ftl::Flags<InputDeviceClass> classes, const PropertyMap* configuration) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800622 mFakeEventHub->addDevice(eventHubId, name, classes);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800623
624 if (configuration) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800625 mFakeEventHub->addConfigurationMap(eventHubId, configuration);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800626 }
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:
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003318 void SetUp() override {
3319 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
3320 InputDeviceClass::ALPHAKEY);
3321 }
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003322 const std::string UNIQUE_ID = "local:0";
Zixuan Qufecb6062022-11-12 04:44:31 +00003323 const KeyboardLayoutInfo DEVICE_KEYBOARD_LAYOUT_INFO = KeyboardLayoutInfo("en-US", "qwerty");
Michael Wrighta9cf4192022-12-01 23:46:39 +00003324 void prepareDisplay(ui::Rotation orientation);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003325
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003326 void testDPadKeyRotation(KeyboardInputMapper& mapper, int32_t originalScanCode,
Arthur Hung2c9a3342019-07-23 14:18:59 +08003327 int32_t originalKeyCode, int32_t rotatedKeyCode,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003328 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003329};
3330
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003331/* Similar to setDisplayInfoAndReconfigure, but pre-populates all parameters except for the
3332 * orientation.
3333 */
Michael Wrighta9cf4192022-12-01 23:46:39 +00003334void KeyboardInputMapperTest::prepareDisplay(ui::Rotation orientation) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003335 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
3336 NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003337}
3338
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003339void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper& mapper,
Arthur Hung2c9a3342019-07-23 14:18:59 +08003340 int32_t originalScanCode, int32_t originalKeyCode,
Linnan Li13bf76a2024-05-05 19:18:02 +08003341 int32_t rotatedKeyCode,
3342 ui::LogicalDisplayId displayId) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003343 NotifyKeyArgs args;
3344
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003345 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003346 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3347 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3348 ASSERT_EQ(originalScanCode, args.scanCode);
3349 ASSERT_EQ(rotatedKeyCode, args.keyCode);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003350 ASSERT_EQ(displayId, args.displayId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003351
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003352 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003353 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3354 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3355 ASSERT_EQ(originalScanCode, args.scanCode);
3356 ASSERT_EQ(rotatedKeyCode, args.keyCode);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003357 ASSERT_EQ(displayId, args.displayId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003358}
3359
Michael Wrightd02c5b62014-02-10 15:10:22 -08003360TEST_F(KeyboardInputMapperTest, GetSources) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003361 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003362 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003363
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003364 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003365}
3366
3367TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) {
3368 const int32_t USAGE_A = 0x070004;
3369 const int32_t USAGE_UNKNOWN = 0x07ffff;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003370 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3371 mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
Chris Yea52ade12020-08-27 16:49:20 -07003372 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, POLICY_FLAG_WAKE);
3373 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, POLICY_FLAG_WAKE);
3374 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, POLICY_FLAG_WAKE);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003375
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003376 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003377 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003378 // Initial metastate is AMETA_NONE.
3379 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003380
3381 // Key down by scan code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003382 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003383 NotifyKeyArgs args;
3384 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3385 ASSERT_EQ(DEVICE_ID, args.deviceId);
3386 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3387 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3388 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3389 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3390 ASSERT_EQ(KEY_HOME, args.scanCode);
3391 ASSERT_EQ(AMETA_NONE, args.metaState);
3392 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3393 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3394 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3395
3396 // Key up by scan code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003397 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003398 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3399 ASSERT_EQ(DEVICE_ID, args.deviceId);
3400 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3401 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3402 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3403 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3404 ASSERT_EQ(KEY_HOME, args.scanCode);
3405 ASSERT_EQ(AMETA_NONE, args.metaState);
3406 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3407 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3408 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3409
3410 // Key down by usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003411 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A);
3412 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, 0, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003413 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3414 ASSERT_EQ(DEVICE_ID, args.deviceId);
3415 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3416 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3417 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3418 ASSERT_EQ(AKEYCODE_A, args.keyCode);
3419 ASSERT_EQ(0, args.scanCode);
3420 ASSERT_EQ(AMETA_NONE, args.metaState);
3421 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3422 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3423 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3424
3425 // Key up by usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003426 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A);
3427 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003428 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3429 ASSERT_EQ(DEVICE_ID, args.deviceId);
3430 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3431 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3432 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3433 ASSERT_EQ(AKEYCODE_A, args.keyCode);
3434 ASSERT_EQ(0, args.scanCode);
3435 ASSERT_EQ(AMETA_NONE, args.metaState);
3436 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3437 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3438 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3439
3440 // Key down with unknown scan code or usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003441 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
3442 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003443 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3444 ASSERT_EQ(DEVICE_ID, args.deviceId);
3445 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3446 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3447 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3448 ASSERT_EQ(0, args.keyCode);
3449 ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
3450 ASSERT_EQ(AMETA_NONE, args.metaState);
3451 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3452 ASSERT_EQ(0U, args.policyFlags);
3453 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3454
3455 // Key up with unknown scan code or usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003456 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
3457 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_UNKNOWN, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003458 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3459 ASSERT_EQ(DEVICE_ID, args.deviceId);
3460 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3461 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3462 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3463 ASSERT_EQ(0, args.keyCode);
3464 ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
3465 ASSERT_EQ(AMETA_NONE, args.metaState);
3466 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3467 ASSERT_EQ(0U, args.policyFlags);
3468 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3469}
3470
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003471TEST_F(KeyboardInputMapperTest, Process_KeyRemapping) {
3472 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
3473 mFakeEventHub->addKey(EVENTHUB_ID, KEY_B, 0, AKEYCODE_B, 0);
3474 mFakeEventHub->addKeyRemapping(EVENTHUB_ID, AKEYCODE_A, AKEYCODE_B);
3475
3476 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003477 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003478
3479 // Key down by scan code.
3480 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_A, 1);
3481 NotifyKeyArgs args;
3482 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3483 ASSERT_EQ(AKEYCODE_B, args.keyCode);
3484
3485 // Key up by scan code.
3486 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 0);
3487 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3488 ASSERT_EQ(AKEYCODE_B, args.keyCode);
3489}
3490
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003491/**
3492 * Ensure that the readTime is set to the time when the EV_KEY is received.
3493 */
3494TEST_F(KeyboardInputMapperTest, Process_SendsReadTime) {
3495 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3496
3497 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003498 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003499 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 =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003520 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003521
Arthur Hung95f68612022-04-07 14:08:22 +08003522 // Initial metastate is AMETA_NONE.
3523 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003524
3525 // Metakey down.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003526 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003527 NotifyKeyArgs args;
3528 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3529 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003530 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
arthurhungdcef2dc2020-08-11 14:47:50 +08003531 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003532
3533 // Key down.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003534 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003535 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3536 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003537 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003538
3539 // Key up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003540 process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_KEY, KEY_A, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003541 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3542 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003543 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003544
3545 // Metakey up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003546 process(mapper, ARBITRARY_TIME + 3, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003547 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3548 ASSERT_EQ(AMETA_NONE, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003549 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
arthurhungdcef2dc2020-08-11 14:47:50 +08003550 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003551}
3552
3553TEST_F(KeyboardInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateDPad) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003554 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3555 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3556 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3557 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003558
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003559 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003560 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003561
Michael Wrighta9cf4192022-12-01 23:46:39 +00003562 prepareDisplay(ui::ROTATION_90);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003563 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3564 KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
3565 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3566 KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
3567 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3568 KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
3569 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3570 KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
3571}
3572
3573TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003574 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3575 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3576 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3577 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003578
Michael Wrightd02c5b62014-02-10 15:10:22 -08003579 addConfigurationProperty("keyboard.orientationAware", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003580 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003581 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003582
Michael Wrighta9cf4192022-12-01 23:46:39 +00003583 prepareDisplay(ui::ROTATION_0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003584 ASSERT_NO_FATAL_FAILURE(
3585 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
3586 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3587 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3588 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3589 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3590 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3591 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003592
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003593 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003594 prepareDisplay(ui::ROTATION_90);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003595 ASSERT_NO_FATAL_FAILURE(
3596 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3597 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3598 AKEYCODE_DPAD_UP, DISPLAY_ID));
3599 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3600 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3601 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3602 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003603
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003604 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003605 prepareDisplay(ui::ROTATION_180);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003606 ASSERT_NO_FATAL_FAILURE(
3607 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3608 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3609 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3610 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3611 AKEYCODE_DPAD_UP, DISPLAY_ID));
3612 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3613 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003614
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003615 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003616 prepareDisplay(ui::ROTATION_270);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003617 ASSERT_NO_FATAL_FAILURE(
3618 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3619 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3620 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3621 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3622 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3623 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3624 AKEYCODE_DPAD_UP, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003625
3626 // Special case: if orientation changes while key is down, we still emit the same keycode
3627 // in the key up as we did in the key down.
3628 NotifyKeyArgs args;
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003629 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003630 prepareDisplay(ui::ROTATION_270);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003631 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003632 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3633 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3634 ASSERT_EQ(KEY_UP, args.scanCode);
3635 ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
3636
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003637 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003638 prepareDisplay(ui::ROTATION_180);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003639 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003640 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3641 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3642 ASSERT_EQ(KEY_UP, args.scanCode);
3643 ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
3644}
3645
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003646TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_NotOrientationAware) {
3647 // If the keyboard is not orientation aware,
3648 // key events should not be associated with a specific display id
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003649 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003650
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003651 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003652 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003653 NotifyKeyArgs args;
3654
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003655 // Display id should be LogicalDisplayId::INVALID without any display configuration.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003656 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003657 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003658 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003659 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003660 ASSERT_EQ(ui::LogicalDisplayId::INVALID, args.displayId);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003661
Michael Wrighta9cf4192022-12-01 23:46:39 +00003662 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003663 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003664 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003665 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003666 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003667 ASSERT_EQ(ui::LogicalDisplayId::INVALID, args.displayId);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003668}
3669
3670TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_OrientationAware) {
3671 // If the keyboard is orientation aware,
3672 // key events should be associated with the internal viewport
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003673 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003674
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003675 addConfigurationProperty("keyboard.orientationAware", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003676 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003677 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003678 NotifyKeyArgs args;
3679
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003680 // Display id should be LogicalDisplayId::INVALID without any display configuration.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003681 // ^--- already checked by the previous test
3682
Michael Wrighta9cf4192022-12-01 23:46:39 +00003683 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003684 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003685 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003686 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003687 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003688 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3689 ASSERT_EQ(DISPLAY_ID, args.displayId);
3690
Linnan Li13bf76a2024-05-05 19:18:02 +08003691 constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003692 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003693 setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003694 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003695 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003696 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003697 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003698 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3699 ASSERT_EQ(newDisplayId, args.displayId);
3700}
3701
Michael Wrightd02c5b62014-02-10 15:10:22 -08003702TEST_F(KeyboardInputMapperTest, GetKeyCodeState) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003703 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003704 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003705
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003706 mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003707 ASSERT_EQ(1, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003708
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003709 mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003710 ASSERT_EQ(0, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003711}
3712
Philip Junker4af3b3d2021-12-14 10:36:55 +01003713TEST_F(KeyboardInputMapperTest, GetKeyCodeForKeyLocation) {
3714 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003715 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Philip Junker4af3b3d2021-12-14 10:36:55 +01003716
3717 mFakeEventHub->addKeyCodeMapping(EVENTHUB_ID, AKEYCODE_Y, AKEYCODE_Z);
3718 ASSERT_EQ(AKEYCODE_Z, mapper.getKeyCodeForKeyLocation(AKEYCODE_Y))
3719 << "If a mapping is available, the result is equal to the mapping";
3720
3721 ASSERT_EQ(AKEYCODE_A, mapper.getKeyCodeForKeyLocation(AKEYCODE_A))
3722 << "If no mapping is available, the result is the key location";
3723}
3724
Michael Wrightd02c5b62014-02-10 15:10:22 -08003725TEST_F(KeyboardInputMapperTest, GetScanCodeState) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003726 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003727 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003728
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003729 mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003730 ASSERT_EQ(1, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003731
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003732 mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003733 ASSERT_EQ(0, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003734}
3735
3736TEST_F(KeyboardInputMapperTest, MarkSupportedKeyCodes) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003737 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003738 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003739
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003740 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003741
Michael Wrightd02c5b62014-02-10 15:10:22 -08003742 uint8_t flags[2] = { 0, 0 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07003743 ASSERT_TRUE(mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_A, AKEYCODE_B}, flags));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003744 ASSERT_TRUE(flags[0]);
3745 ASSERT_FALSE(flags[1]);
3746}
3747
3748TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003749 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3750 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3751 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3752 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3753 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3754 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003755
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003756 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003757 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003758 // Initial metastate is AMETA_NONE.
3759 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003760
3761 // Initialization should have turned all of the lights off.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003762 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3763 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3764 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003765
3766 // Toggle caps lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003767 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3768 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003769 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3770 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3771 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003772 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003773
3774 // Toggle num lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003775 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3776 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003777 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3778 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3779 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003780 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003781
3782 // Toggle caps lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003783 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3784 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003785 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3786 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3787 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003788 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003789
3790 // Toggle scroll lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003791 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3792 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003793 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3794 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3795 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003796 ASSERT_EQ(AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003797
3798 // Toggle num lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003799 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3800 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003801 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3802 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3803 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003804 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003805
3806 // Toggle scroll lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003807 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3808 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003809 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3810 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3811 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003812 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003813}
3814
Chris Yea52ade12020-08-27 16:49:20 -07003815TEST_F(KeyboardInputMapperTest, NoMetaStateWhenMetaKeysNotPresent) {
3816 mFakeEventHub->addKey(EVENTHUB_ID, BTN_A, 0, AKEYCODE_BUTTON_A, 0);
3817 mFakeEventHub->addKey(EVENTHUB_ID, BTN_B, 0, AKEYCODE_BUTTON_B, 0);
3818 mFakeEventHub->addKey(EVENTHUB_ID, BTN_X, 0, AKEYCODE_BUTTON_X, 0);
3819 mFakeEventHub->addKey(EVENTHUB_ID, BTN_Y, 0, AKEYCODE_BUTTON_Y, 0);
3820
3821 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003822 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Chris Yea52ade12020-08-27 16:49:20 -07003823
Chris Yea52ade12020-08-27 16:49:20 -07003824 // Meta state should be AMETA_NONE after reset
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003825 std::list<NotifyArgs> unused = mapper.reset(ARBITRARY_TIME);
Chris Yea52ade12020-08-27 16:49:20 -07003826 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3827 // Meta state should be AMETA_NONE with update, as device doesn't have the keys.
3828 mapper.updateMetaState(AKEYCODE_NUM_LOCK);
3829 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3830
3831 NotifyKeyArgs args;
3832 // Press button "A"
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003833 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_A, 1);
Chris Yea52ade12020-08-27 16:49:20 -07003834 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3835 ASSERT_EQ(AMETA_NONE, args.metaState);
3836 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3837 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3838 ASSERT_EQ(AKEYCODE_BUTTON_A, args.keyCode);
3839
3840 // Button up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003841 process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_KEY, BTN_A, 0);
Chris Yea52ade12020-08-27 16:49:20 -07003842 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3843 ASSERT_EQ(AMETA_NONE, args.metaState);
3844 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3845 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3846 ASSERT_EQ(AKEYCODE_BUTTON_A, args.keyCode);
3847}
3848
Arthur Hung2c9a3342019-07-23 14:18:59 +08003849TEST_F(KeyboardInputMapperTest, Configure_AssignsDisplayPort) {
3850 // keyboard 1.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003851 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3852 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3853 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3854 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003855
3856 // keyboard 2.
3857 const std::string USB2 = "USB2";
arthurhungdcef2dc2020-08-11 14:47:50 +08003858 const std::string DEVICE_NAME2 = "KEYBOARD2";
Arthur Hung2c9a3342019-07-23 14:18:59 +08003859 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003860 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
arthurhungdcef2dc2020-08-11 14:47:50 +08003861 std::shared_ptr<InputDevice> device2 =
3862 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
Dominik Laskowski2f01d772022-03-23 16:01:29 -07003863 ftl::Flags<InputDeviceClass>(0));
arthurhungdcef2dc2020-08-11 14:47:50 +08003864
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003865 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3866 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3867 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3868 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003869
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003870 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003871 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003872
Arpit Singh67ca6842023-04-26 14:43:16 +00003873 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003874 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003875 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3876 mFakePolicy
3877 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003878 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003879 std::list<NotifyArgs> unused =
3880 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003881 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003882 unused += device2->reset(ARBITRARY_TIME);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003883
3884 // Prepared displays and associated info.
3885 constexpr uint8_t hdmi1 = 0;
3886 constexpr uint8_t hdmi2 = 1;
3887 const std::string SECONDARY_UNIQUE_ID = "local:1";
3888
3889 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
3890 mFakePolicy->addInputPortAssociation(USB2, hdmi2);
3891
3892 // No associated display viewport found, should disable the device.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003893 unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003894 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003895 ASSERT_FALSE(device2->isEnabled());
3896
3897 // Prepare second display.
Linnan Li13bf76a2024-05-05 19:18:02 +08003898 constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
Michael Wrighta9cf4192022-12-01 23:46:39 +00003899 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003900 UNIQUE_ID, hdmi1, ViewportType::INTERNAL);
Michael Wrighta9cf4192022-12-01 23:46:39 +00003901 setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003902 SECONDARY_UNIQUE_ID, hdmi2, ViewportType::EXTERNAL);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003903 // Default device will reconfigure above, need additional reconfiguration for another device.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003904 unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003905 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003906
3907 // Device should be enabled after the associated display is found.
3908 ASSERT_TRUE(mDevice->isEnabled());
3909 ASSERT_TRUE(device2->isEnabled());
3910
3911 // Test pad key events
3912 ASSERT_NO_FATAL_FAILURE(
3913 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
3914 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3915 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3916 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3917 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3918 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3919 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3920
3921 ASSERT_NO_FATAL_FAILURE(
3922 testDPadKeyRotation(mapper2, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, newDisplayId));
3923 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3924 AKEYCODE_DPAD_RIGHT, newDisplayId));
3925 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3926 AKEYCODE_DPAD_DOWN, newDisplayId));
3927 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3928 AKEYCODE_DPAD_LEFT, newDisplayId));
3929}
Michael Wrightd02c5b62014-02-10 15:10:22 -08003930
arthurhungc903df12020-08-11 15:08:42 +08003931TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleAfterReattach) {
3932 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3933 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3934 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3935 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3936 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3937 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3938
3939 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003940 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003941 // Initial metastate is AMETA_NONE.
3942 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
arthurhungc903df12020-08-11 15:08:42 +08003943
3944 // Initialization should have turned all of the lights off.
3945 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3946 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3947 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3948
3949 // Toggle caps lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003950 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3951 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003952 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3953 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
3954
3955 // Toggle num lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003956 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3957 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003958 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3959 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
3960
3961 // Toggle scroll lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003962 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3963 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003964 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3965 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
3966
3967 mFakeEventHub->removeDevice(EVENTHUB_ID);
3968 mReader->loopOnce();
3969
3970 // keyboard 2 should default toggle keys.
3971 const std::string USB2 = "USB2";
3972 const std::string DEVICE_NAME2 = "KEYBOARD2";
3973 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
3974 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
3975 std::shared_ptr<InputDevice> device2 =
3976 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
Dominik Laskowski2f01d772022-03-23 16:01:29 -07003977 ftl::Flags<InputDeviceClass>(0));
arthurhungc903df12020-08-11 15:08:42 +08003978 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3979 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
3980 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3981 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3982 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3983 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3984
Arpit Singh67ca6842023-04-26 14:43:16 +00003985 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
arthurhung6fe95782020-10-05 22:41:16 +08003986 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003987 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3988 mFakePolicy
3989 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003990 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003991 std::list<NotifyArgs> unused =
3992 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003993 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003994 unused += device2->reset(ARBITRARY_TIME);
arthurhungc903df12020-08-11 15:08:42 +08003995
3996 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_CAPSL));
3997 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_NUML));
3998 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_SCROLLL));
arthurhung6fe95782020-10-05 22:41:16 +08003999 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON,
4000 mapper2.getMetaState());
arthurhungc903df12020-08-11 15:08:42 +08004001}
4002
Arthur Hungcb40a002021-08-03 14:31:01 +00004003TEST_F(KeyboardInputMapperTest, Process_toggleCapsLockState) {
4004 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
4005 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
4006 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
4007
4008 // Suppose we have two mappers. (DPAD + KEYBOARD)
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004009 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD);
Arthur Hungcb40a002021-08-03 14:31:01 +00004010 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004011 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08004012 // Initial metastate is AMETA_NONE.
4013 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Arthur Hungcb40a002021-08-03 14:31:01 +00004014
4015 mReader->toggleCapsLockState(DEVICE_ID);
4016 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
4017}
4018
Arthur Hungfb3cc112022-04-13 07:39:50 +00004019TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleInMultiDevices) {
4020 // keyboard 1.
4021 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
4022 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
4023 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
4024 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
4025 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
4026 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
4027
4028 KeyboardInputMapper& mapper1 =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004029 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hungfb3cc112022-04-13 07:39:50 +00004030
4031 // keyboard 2.
4032 const std::string USB2 = "USB2";
4033 const std::string DEVICE_NAME2 = "KEYBOARD2";
4034 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
4035 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
4036 std::shared_ptr<InputDevice> device2 =
4037 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
4038 ftl::Flags<InputDeviceClass>(0));
4039 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
4040 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
4041 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
4042 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
4043 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
4044 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
4045
Arpit Singh67ca6842023-04-26 14:43:16 +00004046 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
Arthur Hungfb3cc112022-04-13 07:39:50 +00004047 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00004048 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
4049 mFakePolicy
4050 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004051 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07004052 std::list<NotifyArgs> unused =
4053 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004054 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07004055 unused += device2->reset(ARBITRARY_TIME);
Arthur Hungfb3cc112022-04-13 07:39:50 +00004056
Arthur Hung95f68612022-04-07 14:08:22 +08004057 // Initial metastate is AMETA_NONE.
4058 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
4059 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
4060
4061 // Toggle num lock on and off.
4062 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
4063 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Arthur Hungfb3cc112022-04-13 07:39:50 +00004064 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
4065 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper1.getMetaState());
4066 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper2.getMetaState());
4067
4068 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
4069 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
4070 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
4071 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
4072 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
4073
4074 // Toggle caps lock on and off.
4075 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
4076 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
4077 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
4078 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper1.getMetaState());
4079 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper2.getMetaState());
4080
4081 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
4082 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
4083 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
4084 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
4085 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
4086
4087 // Toggle scroll lock on and off.
4088 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
4089 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
4090 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
4091 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper1.getMetaState());
4092 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper2.getMetaState());
4093
4094 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
4095 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
4096 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
4097 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
4098 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
4099}
4100
Arthur Hung2141d542022-08-23 07:45:21 +00004101TEST_F(KeyboardInputMapperTest, Process_DisabledDevice) {
4102 const int32_t USAGE_A = 0x070004;
4103 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4104 mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
4105
4106 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004107 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung2141d542022-08-23 07:45:21 +00004108 // Key down by scan code.
4109 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
4110 NotifyKeyArgs args;
4111 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4112 ASSERT_EQ(DEVICE_ID, args.deviceId);
4113 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4114 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4115 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
4116 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4117 ASSERT_EQ(KEY_HOME, args.scanCode);
4118 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
4119
4120 // Disable device, it should synthesize cancellation events for down events.
4121 mFakePolicy->addDisabledDevice(DEVICE_ID);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004122 configureDevice(InputReaderConfiguration::Change::ENABLED_STATE);
Arthur Hung2141d542022-08-23 07:45:21 +00004123
4124 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4125 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
4126 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4127 ASSERT_EQ(KEY_HOME, args.scanCode);
4128 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_CANCELED, args.flags);
4129}
4130
Zixuan Qufecb6062022-11-12 04:44:31 +00004131TEST_F(KeyboardInputMapperTest, Configure_AssignKeyboardLayoutInfo) {
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004132 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Zixuan Qufecb6062022-11-12 04:44:31 +00004133 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004134 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
4135 /*changes=*/{});
Zixuan Qufecb6062022-11-12 04:44:31 +00004136
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +00004137 uint32_t generation = mReader->getContext()->getGeneration();
Zixuan Qufecb6062022-11-12 04:44:31 +00004138 mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
4139
4140 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004141 InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
Zixuan Qufecb6062022-11-12 04:44:31 +00004142
4143 InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
4144 ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.languageTag,
4145 deviceInfo.getKeyboardLayoutInfo()->languageTag);
4146 ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.layoutType,
4147 deviceInfo.getKeyboardLayoutInfo()->layoutType);
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +00004148 ASSERT_TRUE(mReader->getContext()->getGeneration() != generation);
4149
4150 // Call change layout association with the same values: Generation shouldn't change
4151 generation = mReader->getContext()->getGeneration();
4152 mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
4153 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
4154 InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
4155 ASSERT_TRUE(mReader->getContext()->getGeneration() == generation);
Zixuan Qufecb6062022-11-12 04:44:31 +00004156}
4157
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004158TEST_F(KeyboardInputMapperTest, LayoutInfoCorrectlyMapped) {
4159 mFakeEventHub->setRawLayoutInfo(EVENTHUB_ID,
4160 RawLayoutInfo{.languageTag = "en", .layoutType = "extended"});
4161
4162 // Configuration
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004163 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004164 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004165 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004166
4167 ASSERT_EQ("en", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->languageTag);
4168 ASSERT_EQ("extended", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->layoutType);
4169}
4170
Justin Chung71ddb432023-03-27 04:29:07 +00004171TEST_F(KeyboardInputMapperTest, Process_GesureEventToSetFlagKeepTouchMode) {
4172 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, POLICY_FLAG_GESTURE);
4173 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004174 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Justin Chung71ddb432023-03-27 04:29:07 +00004175 NotifyKeyArgs args;
4176
4177 // Key down
4178 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFT, 1);
4179 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4180 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_KEEP_TOUCH_MODE, args.flags);
4181}
4182
Prabir Pradhan34f35702024-07-23 21:59:36 +00004183/**
4184 * When there is more than one KeyboardInputMapper for an InputDevice, each mapper should produce
4185 * events that use the shared keyboard source across all mappers. This is to ensure that each
4186 * input device generates key events in a consistent manner, regardless of which mapper produces
4187 * the event.
4188 */
4189TEST_F(KeyboardInputMapperTest, UsesSharedKeyboardSource) {
4190 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4191
4192 // Add a mapper with SOURCE_KEYBOARD
4193 KeyboardInputMapper& keyboardMapper =
4194 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
4195
4196 process(keyboardMapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1);
4197 ASSERT_NO_FATAL_FAILURE(
4198 mFakeListener->assertNotifyKeyWasCalled(WithSource(AINPUT_SOURCE_KEYBOARD)));
4199 process(keyboardMapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0);
4200 ASSERT_NO_FATAL_FAILURE(
4201 mFakeListener->assertNotifyKeyWasCalled(WithSource(AINPUT_SOURCE_KEYBOARD)));
4202
4203 // Add a mapper with SOURCE_DPAD
4204 KeyboardInputMapper& dpadMapper =
4205 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD);
4206 for (auto* mapper : {&keyboardMapper, &dpadMapper}) {
4207 process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1);
4208 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
4209 WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD)));
4210 process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0);
4211 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
4212 WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD)));
4213 }
4214
4215 // Add a mapper with SOURCE_GAMEPAD
4216 KeyboardInputMapper& gamepadMapper =
4217 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_GAMEPAD);
4218 for (auto* mapper : {&keyboardMapper, &dpadMapper, &gamepadMapper}) {
4219 process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1);
4220 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
4221 WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD)));
4222 process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0);
4223 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
4224 WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD)));
4225 }
4226}
4227
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004228// --- KeyboardInputMapperTest_ExternalAlphabeticDevice ---
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004229
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004230class KeyboardInputMapperTest_ExternalAlphabeticDevice : public InputMapperTest {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004231protected:
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004232 void SetUp() override {
4233 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
4234 InputDeviceClass::ALPHAKEY | InputDeviceClass::EXTERNAL);
4235 }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004236};
4237
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004238// --- KeyboardInputMapperTest_ExternalNonAlphabeticDevice ---
4239
4240class KeyboardInputMapperTest_ExternalNonAlphabeticDevice : public InputMapperTest {
4241protected:
4242 void SetUp() override {
4243 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
4244 InputDeviceClass::EXTERNAL);
4245 }
4246};
4247
4248TEST_F(KeyboardInputMapperTest_ExternalAlphabeticDevice, WakeBehavior_AlphabeticKeyboard) {
Vaibhav Devmurari16257862023-03-06 10:06:32 +00004249 // For external devices, keys will trigger wake on key down. Media keys should also trigger
4250 // wake if triggered from external devices.
Powei Fengd041c5d2019-05-03 17:11:33 -07004251
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004252 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, 0);
4253 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
4254 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
4255 POLICY_FLAG_WAKE);
Powei Fengd041c5d2019-05-03 17:11:33 -07004256
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004257 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004258 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Powei Fengd041c5d2019-05-03 17:11:33 -07004259
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004260 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004261 NotifyKeyArgs args;
4262 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4263 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4264
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004265 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004266 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4267 ASSERT_EQ(uint32_t(0), args.policyFlags);
4268
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004269 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004270 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Vaibhav Devmurari16257862023-03-06 10:06:32 +00004271 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
Powei Fengd041c5d2019-05-03 17:11:33 -07004272
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004273 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004274 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4275 ASSERT_EQ(uint32_t(0), args.policyFlags);
4276
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004277 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004278 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4279 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4280
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004281 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004282 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4283 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4284}
4285
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004286TEST_F(KeyboardInputMapperTest_ExternalNonAlphabeticDevice, WakeBehavior_NonAlphabeticKeyboard) {
Vaibhav Devmurari2681a812024-01-11 00:15:35 +00004287 // For external devices, keys will trigger wake on key down. Media keys should not trigger
4288 // wake if triggered from external non-alphaebtic keyboard (e.g. headsets).
4289
4290 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
4291 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
4292 POLICY_FLAG_WAKE);
4293
4294 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004295 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmurari2681a812024-01-11 00:15:35 +00004296
4297 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
4298 NotifyKeyArgs args;
4299 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4300 ASSERT_EQ(uint32_t(0), args.policyFlags);
4301
4302 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
4303 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4304 ASSERT_EQ(uint32_t(0), args.policyFlags);
4305
4306 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1);
4307 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4308 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4309
4310 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0);
4311 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4312 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4313}
4314
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004315TEST_F(KeyboardInputMapperTest_ExternalAlphabeticDevice, DoNotWakeByDefaultBehavior) {
Powei Fengd041c5d2019-05-03 17:11:33 -07004316 // Tv Remote key's wake behavior is prescribed by the keylayout file.
Powei Fengd041c5d2019-05-03 17:11:33 -07004317
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004318 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4319 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
4320 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, POLICY_FLAG_WAKE);
Powei Fengd041c5d2019-05-03 17:11:33 -07004321
Powei Fengd041c5d2019-05-03 17:11:33 -07004322 addConfigurationProperty("keyboard.doNotWakeByDefault", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004323 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004324 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Powei Fengd041c5d2019-05-03 17:11:33 -07004325
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004326 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004327 NotifyKeyArgs args;
4328 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4329 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4330
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004331 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004332 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4333 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4334
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004335 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_DOWN, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004336 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4337 ASSERT_EQ(uint32_t(0), args.policyFlags);
4338
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004339 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_DOWN, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004340 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4341 ASSERT_EQ(uint32_t(0), args.policyFlags);
4342
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004343 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004344 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4345 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4346
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004347 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004348 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4349 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4350}
4351
Michael Wrightd02c5b62014-02-10 15:10:22 -08004352// --- TouchInputMapperTest ---
4353
4354class TouchInputMapperTest : public InputMapperTest {
4355protected:
4356 static const int32_t RAW_X_MIN;
4357 static const int32_t RAW_X_MAX;
4358 static const int32_t RAW_Y_MIN;
4359 static const int32_t RAW_Y_MAX;
4360 static const int32_t RAW_TOUCH_MIN;
4361 static const int32_t RAW_TOUCH_MAX;
4362 static const int32_t RAW_TOOL_MIN;
4363 static const int32_t RAW_TOOL_MAX;
4364 static const int32_t RAW_PRESSURE_MIN;
4365 static const int32_t RAW_PRESSURE_MAX;
4366 static const int32_t RAW_ORIENTATION_MIN;
4367 static const int32_t RAW_ORIENTATION_MAX;
4368 static const int32_t RAW_DISTANCE_MIN;
4369 static const int32_t RAW_DISTANCE_MAX;
4370 static const int32_t RAW_TILT_MIN;
4371 static const int32_t RAW_TILT_MAX;
4372 static const int32_t RAW_ID_MIN;
4373 static const int32_t RAW_ID_MAX;
4374 static const int32_t RAW_SLOT_MIN;
4375 static const int32_t RAW_SLOT_MAX;
4376 static const float X_PRECISION;
4377 static const float Y_PRECISION;
Santos Cordonfa5cf462017-04-05 10:37:00 -07004378 static const float X_PRECISION_VIRTUAL;
4379 static const float Y_PRECISION_VIRTUAL;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004380
4381 static const float GEOMETRIC_SCALE;
Jason Gerecke489fda82012-09-07 17:19:40 -07004382 static const TouchAffineTransformation AFFINE_TRANSFORM;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004383
4384 static const VirtualKeyDefinition VIRTUAL_KEYS[2];
4385
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07004386 const std::string UNIQUE_ID = "local:0";
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004387 const std::string SECONDARY_UNIQUE_ID = "local:1";
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07004388
Michael Wrightd02c5b62014-02-10 15:10:22 -08004389 enum Axes {
4390 POSITION = 1 << 0,
4391 TOUCH = 1 << 1,
4392 TOOL = 1 << 2,
4393 PRESSURE = 1 << 3,
4394 ORIENTATION = 1 << 4,
4395 MINOR = 1 << 5,
4396 ID = 1 << 6,
4397 DISTANCE = 1 << 7,
4398 TILT = 1 << 8,
4399 SLOT = 1 << 9,
4400 TOOL_TYPE = 1 << 10,
4401 };
4402
Michael Wrighta9cf4192022-12-01 23:46:39 +00004403 void prepareDisplay(ui::Rotation orientation, std::optional<uint8_t> port = NO_PORT);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004404 void prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port = NO_PORT);
Michael Wrighta9cf4192022-12-01 23:46:39 +00004405 void prepareVirtualDisplay(ui::Rotation orientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004406 void prepareVirtualKeys();
Jason Gerecke489fda82012-09-07 17:19:40 -07004407 void prepareLocationCalibration();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004408 int32_t toRawX(float displayX);
4409 int32_t toRawY(float displayY);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07004410 int32_t toRotatedRawX(float displayX);
4411 int32_t toRotatedRawY(float displayY);
Jason Gerecke489fda82012-09-07 17:19:40 -07004412 float toCookedX(float rawX, float rawY);
4413 float toCookedY(float rawX, float rawY);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004414 float toDisplayX(int32_t rawX);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004415 float toDisplayX(int32_t rawX, int32_t displayWidth);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004416 float toDisplayY(int32_t rawY);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004417 float toDisplayY(int32_t rawY, int32_t displayHeight);
4418
Michael Wrightd02c5b62014-02-10 15:10:22 -08004419};
4420
4421const int32_t TouchInputMapperTest::RAW_X_MIN = 25;
4422const int32_t TouchInputMapperTest::RAW_X_MAX = 1019;
4423const int32_t TouchInputMapperTest::RAW_Y_MIN = 30;
4424const int32_t TouchInputMapperTest::RAW_Y_MAX = 1009;
4425const int32_t TouchInputMapperTest::RAW_TOUCH_MIN = 0;
4426const int32_t TouchInputMapperTest::RAW_TOUCH_MAX = 31;
4427const int32_t TouchInputMapperTest::RAW_TOOL_MIN = 0;
4428const int32_t TouchInputMapperTest::RAW_TOOL_MAX = 15;
Michael Wrightaa449c92017-12-13 21:21:43 +00004429const int32_t TouchInputMapperTest::RAW_PRESSURE_MIN = 0;
4430const int32_t TouchInputMapperTest::RAW_PRESSURE_MAX = 255;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004431const int32_t TouchInputMapperTest::RAW_ORIENTATION_MIN = -7;
4432const int32_t TouchInputMapperTest::RAW_ORIENTATION_MAX = 7;
4433const int32_t TouchInputMapperTest::RAW_DISTANCE_MIN = 0;
4434const int32_t TouchInputMapperTest::RAW_DISTANCE_MAX = 7;
4435const int32_t TouchInputMapperTest::RAW_TILT_MIN = 0;
4436const int32_t TouchInputMapperTest::RAW_TILT_MAX = 150;
4437const int32_t TouchInputMapperTest::RAW_ID_MIN = 0;
4438const int32_t TouchInputMapperTest::RAW_ID_MAX = 9;
4439const int32_t TouchInputMapperTest::RAW_SLOT_MIN = 0;
4440const int32_t TouchInputMapperTest::RAW_SLOT_MAX = 9;
4441const float TouchInputMapperTest::X_PRECISION = float(RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH;
4442const float TouchInputMapperTest::Y_PRECISION = float(RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT;
Santos Cordonfa5cf462017-04-05 10:37:00 -07004443const float TouchInputMapperTest::X_PRECISION_VIRTUAL =
4444 float(RAW_X_MAX - RAW_X_MIN + 1) / VIRTUAL_DISPLAY_WIDTH;
4445const float TouchInputMapperTest::Y_PRECISION_VIRTUAL =
4446 float(RAW_Y_MAX - RAW_Y_MIN + 1) / VIRTUAL_DISPLAY_HEIGHT;
Jason Gerecke489fda82012-09-07 17:19:40 -07004447const TouchAffineTransformation TouchInputMapperTest::AFFINE_TRANSFORM =
4448 TouchAffineTransformation(1, -2, 3, -4, 5, -6);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004449
4450const float TouchInputMapperTest::GEOMETRIC_SCALE =
4451 avg(float(DISPLAY_WIDTH) / (RAW_X_MAX - RAW_X_MIN + 1),
4452 float(DISPLAY_HEIGHT) / (RAW_Y_MAX - RAW_Y_MIN + 1));
4453
4454const VirtualKeyDefinition TouchInputMapperTest::VIRTUAL_KEYS[2] = {
4455 { KEY_HOME, 60, DISPLAY_HEIGHT + 15, 20, 20 },
4456 { KEY_MENU, DISPLAY_HEIGHT - 60, DISPLAY_WIDTH + 15, 20, 20 },
4457};
4458
Michael Wrighta9cf4192022-12-01 23:46:39 +00004459void TouchInputMapperTest::prepareDisplay(ui::Rotation orientation, std::optional<uint8_t> port) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01004460 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
4461 port, ViewportType::INTERNAL);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004462}
4463
4464void TouchInputMapperTest::prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port) {
4465 setDisplayInfoAndReconfigure(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00004466 ui::ROTATION_0, SECONDARY_UNIQUE_ID, port, type);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004467}
4468
Michael Wrighta9cf4192022-12-01 23:46:39 +00004469void TouchInputMapperTest::prepareVirtualDisplay(ui::Rotation orientation) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01004470 setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH, VIRTUAL_DISPLAY_HEIGHT,
4471 orientation, VIRTUAL_DISPLAY_UNIQUE_ID, NO_PORT,
4472 ViewportType::VIRTUAL);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004473}
4474
Michael Wrightd02c5b62014-02-10 15:10:22 -08004475void TouchInputMapperTest::prepareVirtualKeys() {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004476 mFakeEventHub->addVirtualKeyDefinition(EVENTHUB_ID, VIRTUAL_KEYS[0]);
4477 mFakeEventHub->addVirtualKeyDefinition(EVENTHUB_ID, VIRTUAL_KEYS[1]);
4478 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4479 mFakeEventHub->addKey(EVENTHUB_ID, KEY_MENU, 0, AKEYCODE_MENU, POLICY_FLAG_WAKE);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004480}
4481
Jason Gerecke489fda82012-09-07 17:19:40 -07004482void TouchInputMapperTest::prepareLocationCalibration() {
4483 mFakePolicy->setTouchAffineTransformation(AFFINE_TRANSFORM);
4484}
4485
Michael Wrightd02c5b62014-02-10 15:10:22 -08004486int32_t TouchInputMapperTest::toRawX(float displayX) {
4487 return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH + RAW_X_MIN);
4488}
4489
4490int32_t TouchInputMapperTest::toRawY(float displayY) {
4491 return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT + RAW_Y_MIN);
4492}
4493
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07004494int32_t TouchInputMapperTest::toRotatedRawX(float displayX) {
4495 return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_HEIGHT + RAW_X_MIN);
4496}
4497
4498int32_t TouchInputMapperTest::toRotatedRawY(float displayY) {
4499 return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_WIDTH + RAW_Y_MIN);
4500}
4501
Jason Gerecke489fda82012-09-07 17:19:40 -07004502float TouchInputMapperTest::toCookedX(float rawX, float rawY) {
4503 AFFINE_TRANSFORM.applyTo(rawX, rawY);
4504 return rawX;
4505}
4506
4507float TouchInputMapperTest::toCookedY(float rawX, float rawY) {
4508 AFFINE_TRANSFORM.applyTo(rawX, rawY);
4509 return rawY;
4510}
4511
Michael Wrightd02c5b62014-02-10 15:10:22 -08004512float TouchInputMapperTest::toDisplayX(int32_t rawX) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004513 return toDisplayX(rawX, DISPLAY_WIDTH);
4514}
4515
4516float TouchInputMapperTest::toDisplayX(int32_t rawX, int32_t displayWidth) {
4517 return float(rawX - RAW_X_MIN) * displayWidth / (RAW_X_MAX - RAW_X_MIN + 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004518}
4519
4520float TouchInputMapperTest::toDisplayY(int32_t rawY) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004521 return toDisplayY(rawY, DISPLAY_HEIGHT);
4522}
4523
4524float TouchInputMapperTest::toDisplayY(int32_t rawY, int32_t displayHeight) {
4525 return float(rawY - RAW_Y_MIN) * displayHeight / (RAW_Y_MAX - RAW_Y_MIN + 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004526}
4527
4528
4529// --- SingleTouchInputMapperTest ---
4530
4531class SingleTouchInputMapperTest : public TouchInputMapperTest {
4532protected:
4533 void prepareButtons();
4534 void prepareAxes(int axes);
4535
Biswarup Palb08159b2024-08-22 09:12:19 +00004536 std::list<NotifyArgs> processDown(SingleTouchInputMapper& mapper, int32_t x, int32_t y);
4537 std::list<NotifyArgs> processMove(SingleTouchInputMapper& mapper, int32_t x, int32_t y);
4538 std::list<NotifyArgs> processUp(SingleTouchInputMapper& mappery);
4539 std::list<NotifyArgs> processPressure(SingleTouchInputMapper& mapper, int32_t pressure);
4540 std::list<NotifyArgs> processToolMajor(SingleTouchInputMapper& mapper, int32_t toolMajor);
4541 std::list<NotifyArgs> processDistance(SingleTouchInputMapper& mapper, int32_t distance);
4542 std::list<NotifyArgs> processTilt(SingleTouchInputMapper& mapper, int32_t tiltX, int32_t tiltY);
4543 std::list<NotifyArgs> processKey(SingleTouchInputMapper& mapper, int32_t code, int32_t value);
4544 std::list<NotifyArgs> processSync(SingleTouchInputMapper& mapper);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004545};
4546
4547void SingleTouchInputMapperTest::prepareButtons() {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004548 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004549}
4550
4551void SingleTouchInputMapperTest::prepareAxes(int axes) {
4552 if (axes & POSITION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004553 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
4554 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004555 }
4556 if (axes & PRESSURE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004557 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_PRESSURE, RAW_PRESSURE_MIN,
4558 RAW_PRESSURE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004559 }
4560 if (axes & TOOL) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004561 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TOOL_WIDTH, RAW_TOOL_MIN, RAW_TOOL_MAX, 0,
4562 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004563 }
4564 if (axes & DISTANCE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004565 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_DISTANCE, RAW_DISTANCE_MIN,
4566 RAW_DISTANCE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004567 }
4568 if (axes & TILT) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004569 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TILT_X, RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
4570 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TILT_Y, RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004571 }
4572}
4573
Biswarup Palb08159b2024-08-22 09:12:19 +00004574std::list<NotifyArgs> SingleTouchInputMapperTest::processDown(SingleTouchInputMapper& mapper,
4575 int32_t x, int32_t y) {
4576 std::list<NotifyArgs> args;
4577 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
4578 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, x);
4579 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, y);
4580 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004581}
4582
Biswarup Palb08159b2024-08-22 09:12:19 +00004583std::list<NotifyArgs> SingleTouchInputMapperTest::processMove(SingleTouchInputMapper& mapper,
4584 int32_t x, int32_t y) {
4585 std::list<NotifyArgs> args;
4586 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, x);
4587 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, y);
4588 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004589}
4590
Biswarup Palb08159b2024-08-22 09:12:19 +00004591std::list<NotifyArgs> SingleTouchInputMapperTest::processUp(SingleTouchInputMapper& mapper) {
4592 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004593}
4594
Biswarup Palb08159b2024-08-22 09:12:19 +00004595std::list<NotifyArgs> SingleTouchInputMapperTest::processPressure(SingleTouchInputMapper& mapper,
4596 int32_t pressure) {
4597 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_PRESSURE, pressure);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004598}
4599
Biswarup Palb08159b2024-08-22 09:12:19 +00004600std::list<NotifyArgs> SingleTouchInputMapperTest::processToolMajor(SingleTouchInputMapper& mapper,
4601 int32_t toolMajor) {
4602 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TOOL_WIDTH, toolMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004603}
4604
Biswarup Palb08159b2024-08-22 09:12:19 +00004605std::list<NotifyArgs> SingleTouchInputMapperTest::processDistance(SingleTouchInputMapper& mapper,
4606 int32_t distance) {
4607 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_DISTANCE, distance);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004608}
4609
Biswarup Palb08159b2024-08-22 09:12:19 +00004610std::list<NotifyArgs> SingleTouchInputMapperTest::processTilt(SingleTouchInputMapper& mapper,
4611 int32_t tiltX, int32_t tiltY) {
4612 std::list<NotifyArgs> args;
4613 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TILT_X, tiltX);
4614 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TILT_Y, tiltY);
4615 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004616}
4617
Biswarup Palb08159b2024-08-22 09:12:19 +00004618std::list<NotifyArgs> SingleTouchInputMapperTest::processKey(SingleTouchInputMapper& mapper,
4619 int32_t code, int32_t value) {
4620 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004621}
4622
Biswarup Palb08159b2024-08-22 09:12:19 +00004623std::list<NotifyArgs> SingleTouchInputMapperTest::processSync(SingleTouchInputMapper& mapper) {
4624 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004625}
4626
Michael Wrightd02c5b62014-02-10 15:10:22 -08004627TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndNotACursor_ReturnsPointer) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004628 prepareButtons();
4629 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00004630 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004631
Josep del Río2d8c79a2023-01-23 19:33:50 +00004632 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004633}
4634
Michael Wrightd02c5b62014-02-10 15:10:22 -08004635TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004636 prepareButtons();
4637 prepareAxes(POSITION);
4638 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00004639 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004640
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004641 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004642}
4643
4644TEST_F(SingleTouchInputMapperTest, GetKeyCodeState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004645 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004646 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004647 prepareButtons();
4648 prepareAxes(POSITION);
4649 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004650 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004651
4652 // Unknown key.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004653 ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004654
4655 // Virtual key is down.
4656 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4657 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4658 processDown(mapper, x, y);
4659 processSync(mapper);
4660 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4661
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004662 ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004663
4664 // Virtual key is up.
4665 processUp(mapper);
4666 processSync(mapper);
4667 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4668
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004669 ASSERT_EQ(AKEY_STATE_UP, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004670}
4671
4672TEST_F(SingleTouchInputMapperTest, GetScanCodeState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004673 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004674 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004675 prepareButtons();
4676 prepareAxes(POSITION);
4677 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004678 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004679
4680 // Unknown key.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004681 ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004682
4683 // Virtual key is down.
4684 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4685 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4686 processDown(mapper, x, y);
4687 processSync(mapper);
4688 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4689
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004690 ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004691
4692 // Virtual key is up.
4693 processUp(mapper);
4694 processSync(mapper);
4695 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4696
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004697 ASSERT_EQ(AKEY_STATE_UP, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004698}
4699
4700TEST_F(SingleTouchInputMapperTest, MarkSupportedKeyCodes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004701 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004702 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004703 prepareButtons();
4704 prepareAxes(POSITION);
4705 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004706 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004707
Michael Wrightd02c5b62014-02-10 15:10:22 -08004708 uint8_t flags[2] = { 0, 0 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07004709 ASSERT_TRUE(
4710 mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_HOME, AKEYCODE_A}, flags));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004711 ASSERT_TRUE(flags[0]);
4712 ASSERT_FALSE(flags[1]);
4713}
4714
Biswarup Palb08159b2024-08-22 09:12:19 +00004715TEST_F(SingleTouchInputMapperTest, DeviceTypeChange_RecalculatesRawToDisplayTransform) {
4716 prepareDisplay(ui::ROTATION_0);
4717 prepareAxes(POSITION);
4718 addConfigurationProperty("touch.deviceType", "touchScreen");
4719 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
4720
4721 const int32_t x = 900;
4722 const int32_t y = 75;
4723 std::list<NotifyArgs> args;
4724 args += processDown(mapper, x, y);
4725 args += processSync(mapper);
4726
4727 // Assert that motion event is received in display coordinate space for deviceType touchScreen.
4728 ASSERT_THAT(args,
4729 ElementsAre(VariantWith<NotifyMotionArgs>(
4730 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4731 WithCoords(toDisplayX(x), toDisplayY(y))))));
4732
4733 // Add device type association after the device was created.
4734 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
4735 // Send update to the mapper.
4736 std::list<NotifyArgs> unused =
4737 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
4738 InputReaderConfiguration::Change::DEVICE_TYPE /*changes*/);
4739
4740 args.clear();
4741 args += processDown(mapper, x, y);
4742 args += processSync(mapper);
4743
4744 // Assert that motion event is received in raw coordinate space for deviceType touchNavigation.
4745 ASSERT_THAT(args,
4746 ElementsAre(VariantWith<NotifyMotionArgs>(
4747 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4748 WithCoords(x - RAW_X_MIN, y - RAW_Y_MIN)))));
4749}
4750
Michael Wrightd02c5b62014-02-10 15:10:22 -08004751TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNormally_SendsKeyDownAndKeyUp) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004752 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004753 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004754 prepareButtons();
4755 prepareAxes(POSITION);
4756 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004757 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004758
arthurhungdcef2dc2020-08-11 14:47:50 +08004759 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004760
4761 NotifyKeyArgs args;
4762
4763 // Press virtual key.
4764 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4765 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4766 processDown(mapper, x, y);
4767 processSync(mapper);
4768
4769 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4770 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4771 ASSERT_EQ(DEVICE_ID, args.deviceId);
4772 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4773 ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
4774 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
4775 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
4776 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4777 ASSERT_EQ(KEY_HOME, args.scanCode);
4778 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
4779 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
4780
4781 // Release virtual key.
4782 processUp(mapper);
4783 processSync(mapper);
4784
4785 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4786 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4787 ASSERT_EQ(DEVICE_ID, args.deviceId);
4788 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4789 ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
4790 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
4791 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
4792 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4793 ASSERT_EQ(KEY_HOME, args.scanCode);
4794 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
4795 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
4796
4797 // Should not have sent any motions.
4798 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4799}
4800
4801TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfBounds_SendsKeyDownAndKeyCancel) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004802 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004803 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004804 prepareButtons();
4805 prepareAxes(POSITION);
4806 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004807 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004808
arthurhungdcef2dc2020-08-11 14:47:50 +08004809 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004810
4811 NotifyKeyArgs keyArgs;
4812
4813 // Press virtual key.
4814 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4815 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4816 processDown(mapper, x, y);
4817 processSync(mapper);
4818
4819 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
4820 ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
4821 ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
4822 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
4823 ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
4824 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
4825 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, keyArgs.flags);
4826 ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
4827 ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
4828 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
4829 ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
4830
4831 // Move out of bounds. This should generate a cancel and a pointer down since we moved
4832 // into the display area.
4833 y -= 100;
4834 processMove(mapper, x, y);
4835 processSync(mapper);
4836
4837 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
4838 ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
4839 ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
4840 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
4841 ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
4842 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
4843 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
4844 | AKEY_EVENT_FLAG_CANCELED, keyArgs.flags);
4845 ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
4846 ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
4847 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
4848 ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
4849
4850 NotifyMotionArgs motionArgs;
4851 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4852 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4853 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4854 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4855 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4856 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4857 ASSERT_EQ(0, motionArgs.flags);
4858 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4859 ASSERT_EQ(0, motionArgs.buttonState);
4860 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004861 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004862 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004863 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004864 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4865 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4866 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4867 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4868 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4869
4870 // Keep moving out of bounds. Should generate a pointer move.
4871 y -= 50;
4872 processMove(mapper, x, y);
4873 processSync(mapper);
4874
4875 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4876 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4877 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4878 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4879 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4880 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
4881 ASSERT_EQ(0, motionArgs.flags);
4882 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4883 ASSERT_EQ(0, motionArgs.buttonState);
4884 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004885 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004886 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004887 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004888 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4889 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4890 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4891 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4892 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4893
4894 // Release out of bounds. Should generate a pointer up.
4895 processUp(mapper);
4896 processSync(mapper);
4897
4898 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4899 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4900 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4901 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4902 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4903 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4904 ASSERT_EQ(0, motionArgs.flags);
4905 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4906 ASSERT_EQ(0, motionArgs.buttonState);
4907 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004908 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004909 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004910 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004911 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4912 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4913 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4914 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4915 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4916
4917 // Should not have sent any more keys or motions.
4918 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4919 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4920}
4921
4922TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMovesIn_SendsDownAsTouchEntersDisplay) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004923 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004924 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004925 prepareButtons();
4926 prepareAxes(POSITION);
4927 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004928 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004929
arthurhungdcef2dc2020-08-11 14:47:50 +08004930 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004931
4932 NotifyMotionArgs motionArgs;
4933
4934 // Initially go down out of bounds.
4935 int32_t x = -10;
4936 int32_t y = -10;
4937 processDown(mapper, x, y);
4938 processSync(mapper);
4939
4940 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4941
4942 // Move into the display area. Should generate a pointer down.
4943 x = 50;
4944 y = 75;
4945 processMove(mapper, x, y);
4946 processSync(mapper);
4947
4948 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4949 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4950 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4951 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4952 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4953 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4954 ASSERT_EQ(0, motionArgs.flags);
4955 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4956 ASSERT_EQ(0, motionArgs.buttonState);
4957 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004958 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004959 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004960 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004961 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4962 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4963 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4964 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4965 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4966
4967 // Release. Should generate a pointer up.
4968 processUp(mapper);
4969 processSync(mapper);
4970
4971 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4972 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4973 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4974 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4975 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4976 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4977 ASSERT_EQ(0, motionArgs.flags);
4978 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4979 ASSERT_EQ(0, motionArgs.buttonState);
4980 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004981 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004982 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004983 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004984 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4985 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4986 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4987 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4988 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4989
4990 // Should not have sent any more keys or motions.
4991 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4992 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4993}
4994
Santos Cordonfa5cf462017-04-05 10:37:00 -07004995TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture_VirtualDisplay) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004996 addConfigurationProperty("touch.deviceType", "touchScreen");
4997 addConfigurationProperty("touch.displayId", VIRTUAL_DISPLAY_UNIQUE_ID);
4998
Michael Wrighta9cf4192022-12-01 23:46:39 +00004999 prepareVirtualDisplay(ui::ROTATION_0);
Santos Cordonfa5cf462017-04-05 10:37:00 -07005000 prepareButtons();
5001 prepareAxes(POSITION);
5002 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00005003 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Santos Cordonfa5cf462017-04-05 10:37:00 -07005004
arthurhungdcef2dc2020-08-11 14:47:50 +08005005 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Santos Cordonfa5cf462017-04-05 10:37:00 -07005006
5007 NotifyMotionArgs motionArgs;
5008
5009 // Down.
5010 int32_t x = 100;
5011 int32_t y = 125;
5012 processDown(mapper, x, y);
5013 processSync(mapper);
5014
5015 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5016 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5017 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5018 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
5019 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5020 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5021 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5022 ASSERT_EQ(0, motionArgs.flags);
5023 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5024 ASSERT_EQ(0, motionArgs.buttonState);
5025 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005026 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07005027 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005028 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07005029 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5030 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
5031 1, 0, 0, 0, 0, 0, 0, 0));
5032 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
5033 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
5034 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5035
5036 // Move.
5037 x += 50;
5038 y += 75;
5039 processMove(mapper, x, y);
5040 processSync(mapper);
5041
5042 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5043 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5044 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5045 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
5046 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5047 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5048 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5049 ASSERT_EQ(0, motionArgs.flags);
5050 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5051 ASSERT_EQ(0, motionArgs.buttonState);
5052 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005053 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07005054 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005055 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07005056 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5057 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
5058 1, 0, 0, 0, 0, 0, 0, 0));
5059 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
5060 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
5061 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5062
5063 // Up.
5064 processUp(mapper);
5065 processSync(mapper);
5066
5067 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5068 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5069 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5070 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
5071 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5072 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5073 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5074 ASSERT_EQ(0, motionArgs.flags);
5075 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5076 ASSERT_EQ(0, motionArgs.buttonState);
5077 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005078 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07005079 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005080 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07005081 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5082 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
5083 1, 0, 0, 0, 0, 0, 0, 0));
5084 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
5085 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
5086 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5087
5088 // Should not have sent any more keys or motions.
5089 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5090 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5091}
5092
Michael Wrightd02c5b62014-02-10 15:10:22 -08005093TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005094 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005095 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005096 prepareButtons();
5097 prepareAxes(POSITION);
5098 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00005099 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005100
arthurhungdcef2dc2020-08-11 14:47:50 +08005101 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005102
5103 NotifyMotionArgs motionArgs;
5104
5105 // Down.
5106 int32_t x = 100;
5107 int32_t y = 125;
5108 processDown(mapper, x, y);
5109 processSync(mapper);
5110
5111 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5112 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5113 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5114 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5115 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5116 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5117 ASSERT_EQ(0, motionArgs.flags);
5118 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5119 ASSERT_EQ(0, motionArgs.buttonState);
5120 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005121 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08005122 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005123 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005124 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5125 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
5126 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5127 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5128 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5129
5130 // Move.
5131 x += 50;
5132 y += 75;
5133 processMove(mapper, x, y);
5134 processSync(mapper);
5135
5136 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5137 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5138 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5139 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5140 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5141 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5142 ASSERT_EQ(0, motionArgs.flags);
5143 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5144 ASSERT_EQ(0, motionArgs.buttonState);
5145 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005146 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08005147 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005148 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005149 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5150 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
5151 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5152 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5153 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5154
5155 // Up.
5156 processUp(mapper);
5157 processSync(mapper);
5158
5159 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5160 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5161 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5162 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5163 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5164 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5165 ASSERT_EQ(0, motionArgs.flags);
5166 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5167 ASSERT_EQ(0, motionArgs.buttonState);
5168 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005169 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08005170 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005171 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005172 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5173 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
5174 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5175 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5176 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5177
5178 // Should not have sent any more keys or motions.
5179 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5180 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5181}
5182
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005183TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_DoesNotRotateMotions) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005184 addConfigurationProperty("touch.deviceType", "touchScreen");
5185 prepareButtons();
5186 prepareAxes(POSITION);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005187 // InputReader works in the un-rotated coordinate space, so orientation-aware devices do not
5188 // need to be rotated. Touchscreens are orientation-aware by default.
Arpit Singha8c236b2023-04-25 13:56:05 +00005189 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005190
5191 NotifyMotionArgs args;
5192
5193 // Rotation 90.
Michael Wrighta9cf4192022-12-01 23:46:39 +00005194 prepareDisplay(ui::ROTATION_90);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005195 processDown(mapper, toRawX(50), toRawY(75));
5196 processSync(mapper);
5197
5198 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5199 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5200 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5201
5202 processUp(mapper);
5203 processSync(mapper);
5204 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5205}
5206
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005207TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_RotatesMotions) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005208 addConfigurationProperty("touch.deviceType", "touchScreen");
5209 prepareButtons();
5210 prepareAxes(POSITION);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005211 // Since InputReader works in the un-rotated coordinate space, only devices that are not
5212 // orientation-aware are affected by display rotation.
5213 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00005214 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005215
5216 NotifyMotionArgs args;
5217
5218 // Rotation 0.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005219 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005220 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005221 processDown(mapper, toRawX(50), toRawY(75));
5222 processSync(mapper);
5223
5224 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5225 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5226 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5227
5228 processUp(mapper);
5229 processSync(mapper);
5230 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5231
5232 // Rotation 90.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005233 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005234 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005235 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005236 processSync(mapper);
5237
5238 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5239 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5240 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5241
5242 processUp(mapper);
5243 processSync(mapper);
5244 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5245
5246 // Rotation 180.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005247 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005248 prepareDisplay(ui::ROTATION_180);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005249 processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
5250 processSync(mapper);
5251
5252 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5253 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5254 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5255
5256 processUp(mapper);
5257 processSync(mapper);
5258 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5259
5260 // Rotation 270.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005261 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005262 prepareDisplay(ui::ROTATION_270);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005263 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005264 processSync(mapper);
5265
5266 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5267 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5268 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5269
5270 processUp(mapper);
5271 processSync(mapper);
5272 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5273}
5274
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005275TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation0_RotatesMotions) {
5276 addConfigurationProperty("touch.deviceType", "touchScreen");
5277 prepareButtons();
5278 prepareAxes(POSITION);
5279 addConfigurationProperty("touch.orientationAware", "1");
5280 addConfigurationProperty("touch.orientation", "ORIENTATION_0");
5281 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005282 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005283 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005284 NotifyMotionArgs args;
5285
5286 // Orientation 0.
5287 processDown(mapper, toRawX(50), toRawY(75));
5288 processSync(mapper);
5289
5290 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5291 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5292 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5293
5294 processUp(mapper);
5295 processSync(mapper);
5296 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5297}
5298
5299TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation90_RotatesMotions) {
5300 addConfigurationProperty("touch.deviceType", "touchScreen");
5301 prepareButtons();
5302 prepareAxes(POSITION);
5303 addConfigurationProperty("touch.orientationAware", "1");
5304 addConfigurationProperty("touch.orientation", "ORIENTATION_90");
5305 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005306 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005307 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005308 NotifyMotionArgs args;
5309
5310 // Orientation 90.
5311 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
5312 processSync(mapper);
5313
5314 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5315 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5316 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5317
5318 processUp(mapper);
5319 processSync(mapper);
5320 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5321}
5322
5323TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation180_RotatesMotions) {
5324 addConfigurationProperty("touch.deviceType", "touchScreen");
5325 prepareButtons();
5326 prepareAxes(POSITION);
5327 addConfigurationProperty("touch.orientationAware", "1");
5328 addConfigurationProperty("touch.orientation", "ORIENTATION_180");
5329 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005330 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005331 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005332 NotifyMotionArgs args;
5333
5334 // Orientation 180.
5335 processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
5336 processSync(mapper);
5337
5338 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5339 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5340 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5341
5342 processUp(mapper);
5343 processSync(mapper);
5344 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5345}
5346
5347TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation270_RotatesMotions) {
5348 addConfigurationProperty("touch.deviceType", "touchScreen");
5349 prepareButtons();
5350 prepareAxes(POSITION);
5351 addConfigurationProperty("touch.orientationAware", "1");
5352 addConfigurationProperty("touch.orientation", "ORIENTATION_270");
5353 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005354 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005355 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005356 NotifyMotionArgs args;
5357
5358 // Orientation 270.
5359 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
5360 processSync(mapper);
5361
5362 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5363 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5364 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5365
5366 processUp(mapper);
5367 processSync(mapper);
5368 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5369}
5370
5371TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationSpecified_RotatesMotionWithDisplay) {
5372 addConfigurationProperty("touch.deviceType", "touchScreen");
5373 prepareButtons();
5374 prepareAxes(POSITION);
5375 // Since InputReader works in the un-rotated coordinate space, only devices that are not
5376 // orientation-aware are affected by display rotation.
5377 addConfigurationProperty("touch.orientationAware", "0");
5378 addConfigurationProperty("touch.orientation", "ORIENTATION_90");
Arpit Singha8c236b2023-04-25 13:56:05 +00005379 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005380
5381 NotifyMotionArgs args;
5382
5383 // Orientation 90, Rotation 0.
5384 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005385 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005386 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
5387 processSync(mapper);
5388
5389 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5390 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5391 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5392
5393 processUp(mapper);
5394 processSync(mapper);
5395 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5396
5397 // Orientation 90, Rotation 90.
5398 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005399 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005400 processDown(mapper, toRawX(50), toRawY(75));
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005401 processSync(mapper);
5402
5403 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5404 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5405 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5406
5407 processUp(mapper);
5408 processSync(mapper);
5409 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5410
5411 // Orientation 90, Rotation 180.
5412 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005413 prepareDisplay(ui::ROTATION_180);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005414 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
5415 processSync(mapper);
5416
5417 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5418 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5419 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5420
5421 processUp(mapper);
5422 processSync(mapper);
5423 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5424
5425 // Orientation 90, Rotation 270.
5426 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005427 prepareDisplay(ui::ROTATION_270);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005428 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 -07005429 processSync(mapper);
5430
5431 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5432 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5433 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5434
5435 processUp(mapper);
5436 processSync(mapper);
5437 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5438}
5439
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005440TEST_F(SingleTouchInputMapperTest, Process_IgnoresTouchesOutsidePhysicalFrame) {
5441 addConfigurationProperty("touch.deviceType", "touchScreen");
5442 prepareButtons();
5443 prepareAxes(POSITION);
5444 addConfigurationProperty("touch.orientationAware", "1");
5445 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005446 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005447
5448 // Set a physical frame in the display viewport.
5449 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
5450 viewport->physicalLeft = 20;
5451 viewport->physicalTop = 600;
5452 viewport->physicalRight = 30;
5453 viewport->physicalBottom = 610;
5454 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00005455 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005456
5457 // Start the touch.
5458 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
5459 processSync(mapper);
5460
5461 // Expect all input starting outside the physical frame to be ignored.
5462 const std::array<Point, 6> outsidePoints = {
5463 {{0, 0}, {19, 605}, {31, 605}, {25, 599}, {25, 611}, {DISPLAY_WIDTH, DISPLAY_HEIGHT}}};
5464 for (const auto& p : outsidePoints) {
5465 processMove(mapper, toRawX(p.x), toRawY(p.y));
5466 processSync(mapper);
5467 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5468 }
5469
5470 // Move the touch into the physical frame.
5471 processMove(mapper, toRawX(25), toRawY(605));
5472 processSync(mapper);
5473 NotifyMotionArgs args;
5474 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5475 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
5476 EXPECT_NEAR(25, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5477 EXPECT_NEAR(605, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5478
5479 // Once the touch down is reported, continue reporting input, even if it is outside the frame.
5480 for (const auto& p : outsidePoints) {
5481 processMove(mapper, toRawX(p.x), toRawY(p.y));
5482 processSync(mapper);
5483 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5484 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
5485 EXPECT_NEAR(p.x, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5486 EXPECT_NEAR(p.y, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5487 }
5488
5489 processUp(mapper);
5490 processSync(mapper);
5491 EXPECT_NO_FATAL_FAILURE(
5492 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
5493}
5494
Harry Cutts1db43992023-06-19 17:05:07 +00005495TEST_F(SingleTouchInputMapperTest, Process_DoesntCheckPhysicalFrameForTouchpads) {
Harry Cutts1db43992023-06-19 17:05:07 +00005496 addConfigurationProperty("touch.deviceType", "pointer");
5497 prepareAxes(POSITION);
5498 prepareDisplay(ui::ROTATION_0);
5499 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
5500
5501 // Set a physical frame in the display viewport.
5502 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
5503 viewport->physicalLeft = 20;
5504 viewport->physicalTop = 600;
5505 viewport->physicalRight = 30;
5506 viewport->physicalBottom = 610;
5507 mFakePolicy->updateViewport(*viewport);
5508 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
5509
5510 // Start the touch.
5511 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
5512 processSync(mapper);
5513
5514 // Expect all input starting outside the physical frame to result in NotifyMotionArgs being
5515 // produced.
5516 const std::array<Point, 6> outsidePoints = {
5517 {{0, 0}, {19, 605}, {31, 605}, {25, 599}, {25, 611}, {DISPLAY_WIDTH, DISPLAY_HEIGHT}}};
5518 for (const auto& p : outsidePoints) {
5519 processMove(mapper, toRawX(p.x), toRawY(p.y));
5520 processSync(mapper);
5521 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5522 }
5523}
5524
Michael Wrightd02c5b62014-02-10 15:10:22 -08005525TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005526 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005527 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005528 prepareButtons();
5529 prepareAxes(POSITION | PRESSURE | TOOL | DISTANCE | TILT);
Arpit Singha8c236b2023-04-25 13:56:05 +00005530 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005531
5532 // These calculations are based on the input device calibration documentation.
5533 int32_t rawX = 100;
5534 int32_t rawY = 200;
5535 int32_t rawPressure = 10;
5536 int32_t rawToolMajor = 12;
5537 int32_t rawDistance = 2;
5538 int32_t rawTiltX = 30;
5539 int32_t rawTiltY = 110;
5540
5541 float x = toDisplayX(rawX);
5542 float y = toDisplayY(rawY);
5543 float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
5544 float size = float(rawToolMajor) / RAW_TOOL_MAX;
5545 float tool = float(rawToolMajor) * GEOMETRIC_SCALE;
5546 float distance = float(rawDistance);
5547
5548 float tiltCenter = (RAW_TILT_MAX + RAW_TILT_MIN) * 0.5f;
5549 float tiltScale = M_PI / 180;
5550 float tiltXAngle = (rawTiltX - tiltCenter) * tiltScale;
5551 float tiltYAngle = (rawTiltY - tiltCenter) * tiltScale;
5552 float orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
5553 float tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
5554
5555 processDown(mapper, rawX, rawY);
5556 processPressure(mapper, rawPressure);
5557 processToolMajor(mapper, rawToolMajor);
5558 processDistance(mapper, rawDistance);
5559 processTilt(mapper, rawTiltX, rawTiltY);
5560 processSync(mapper);
5561
5562 NotifyMotionArgs args;
5563 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5564 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
5565 x, y, pressure, size, tool, tool, tool, tool, orientation, distance));
5566 ASSERT_EQ(tilt, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TILT));
Prabir Pradhan9a53b552024-06-04 02:59:40 +00005567 ASSERT_EQ(args.flags,
5568 AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION |
5569 AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005570}
5571
Jason Gerecke489fda82012-09-07 17:19:40 -07005572TEST_F(SingleTouchInputMapperTest, Process_XYAxes_AffineCalibration) {
Jason Gerecke489fda82012-09-07 17:19:40 -07005573 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005574 prepareDisplay(ui::ROTATION_0);
Jason Gerecke489fda82012-09-07 17:19:40 -07005575 prepareLocationCalibration();
5576 prepareButtons();
5577 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005578 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Jason Gerecke489fda82012-09-07 17:19:40 -07005579
5580 int32_t rawX = 100;
5581 int32_t rawY = 200;
5582
5583 float x = toDisplayX(toCookedX(rawX, rawY));
5584 float y = toDisplayY(toCookedY(rawX, rawY));
5585
5586 processDown(mapper, rawX, rawY);
5587 processSync(mapper);
5588
5589 NotifyMotionArgs args;
5590 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5591 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
5592 x, y, 1, 0, 0, 0, 0, 0, 0, 0));
5593}
5594
Michael Wrightd02c5b62014-02-10 15:10:22 -08005595TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllButtons) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005596 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005597 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005598 prepareButtons();
5599 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005600 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005601
5602 NotifyMotionArgs motionArgs;
5603 NotifyKeyArgs keyArgs;
5604
5605 processDown(mapper, 100, 200);
5606 processSync(mapper);
5607 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5608 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5609 ASSERT_EQ(0, motionArgs.buttonState);
5610
5611 // press BTN_LEFT, release BTN_LEFT
5612 processKey(mapper, BTN_LEFT, 1);
5613 processSync(mapper);
5614 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5615 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5616 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
5617
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005618 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5619 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5620 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
5621
Michael Wrightd02c5b62014-02-10 15:10:22 -08005622 processKey(mapper, BTN_LEFT, 0);
5623 processSync(mapper);
5624 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005625 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005626 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005627
5628 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005629 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005630 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005631
5632 // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
5633 processKey(mapper, BTN_RIGHT, 1);
5634 processKey(mapper, BTN_MIDDLE, 1);
5635 processSync(mapper);
5636 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5637 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5638 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
5639 motionArgs.buttonState);
5640
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005641 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5642 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5643 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
5644
5645 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5646 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5647 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
5648 motionArgs.buttonState);
5649
Michael Wrightd02c5b62014-02-10 15:10:22 -08005650 processKey(mapper, BTN_RIGHT, 0);
5651 processSync(mapper);
5652 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005653 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005654 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005655
5656 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005657 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005658 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005659
5660 processKey(mapper, BTN_MIDDLE, 0);
5661 processSync(mapper);
5662 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005663 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005664 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005665
5666 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005667 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005668 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005669
5670 // press BTN_BACK, release BTN_BACK
5671 processKey(mapper, BTN_BACK, 1);
5672 processSync(mapper);
5673 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5674 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5675 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005676
Michael Wrightd02c5b62014-02-10 15:10:22 -08005677 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005678 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005679 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
5680
5681 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5682 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5683 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005684
5685 processKey(mapper, BTN_BACK, 0);
5686 processSync(mapper);
5687 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005688 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005689 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005690
5691 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005692 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005693 ASSERT_EQ(0, motionArgs.buttonState);
5694
Michael Wrightd02c5b62014-02-10 15:10:22 -08005695 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5696 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5697 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
5698
5699 // press BTN_SIDE, release BTN_SIDE
5700 processKey(mapper, BTN_SIDE, 1);
5701 processSync(mapper);
5702 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5703 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5704 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005705
Michael Wrightd02c5b62014-02-10 15:10:22 -08005706 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005707 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005708 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
5709
5710 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5711 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5712 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005713
5714 processKey(mapper, BTN_SIDE, 0);
5715 processSync(mapper);
5716 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005717 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005718 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005719
5720 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005721 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005722 ASSERT_EQ(0, motionArgs.buttonState);
5723
Michael Wrightd02c5b62014-02-10 15:10:22 -08005724 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5725 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5726 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
5727
5728 // press BTN_FORWARD, release BTN_FORWARD
5729 processKey(mapper, BTN_FORWARD, 1);
5730 processSync(mapper);
5731 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5732 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5733 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005734
Michael Wrightd02c5b62014-02-10 15:10:22 -08005735 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005736 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005737 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
5738
5739 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5740 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5741 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005742
5743 processKey(mapper, BTN_FORWARD, 0);
5744 processSync(mapper);
5745 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005746 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005747 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005748
5749 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005750 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005751 ASSERT_EQ(0, motionArgs.buttonState);
5752
Michael Wrightd02c5b62014-02-10 15:10:22 -08005753 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5754 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5755 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
5756
5757 // press BTN_EXTRA, release BTN_EXTRA
5758 processKey(mapper, BTN_EXTRA, 1);
5759 processSync(mapper);
5760 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5761 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5762 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005763
Michael Wrightd02c5b62014-02-10 15:10:22 -08005764 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005765 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005766 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
5767
5768 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5769 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5770 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005771
5772 processKey(mapper, BTN_EXTRA, 0);
5773 processSync(mapper);
5774 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005775 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005776 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005777
5778 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005779 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005780 ASSERT_EQ(0, motionArgs.buttonState);
5781
Michael Wrightd02c5b62014-02-10 15:10:22 -08005782 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5783 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5784 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
5785
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005786 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5787
Michael Wrightd02c5b62014-02-10 15:10:22 -08005788 // press BTN_STYLUS, release BTN_STYLUS
5789 processKey(mapper, BTN_STYLUS, 1);
5790 processSync(mapper);
5791 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5792 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005793 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
5794
5795 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5796 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5797 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005798
5799 processKey(mapper, BTN_STYLUS, 0);
5800 processSync(mapper);
5801 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005802 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005803 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005804
5805 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005806 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005807 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005808
5809 // press BTN_STYLUS2, release BTN_STYLUS2
5810 processKey(mapper, BTN_STYLUS2, 1);
5811 processSync(mapper);
5812 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5813 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005814 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
5815
5816 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5817 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5818 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005819
5820 processKey(mapper, BTN_STYLUS2, 0);
5821 processSync(mapper);
5822 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005823 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005824 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005825
5826 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005827 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005828 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005829
5830 // release touch
5831 processUp(mapper);
5832 processSync(mapper);
5833 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5834 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5835 ASSERT_EQ(0, motionArgs.buttonState);
5836}
5837
5838TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005839 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005840 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005841 prepareButtons();
5842 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005843 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005844
5845 NotifyMotionArgs motionArgs;
5846
5847 // default tool type is finger
5848 processDown(mapper, 100, 200);
5849 processSync(mapper);
5850 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5851 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005852 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005853
5854 // eraser
5855 processKey(mapper, BTN_TOOL_RUBBER, 1);
5856 processSync(mapper);
5857 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5858 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005859 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005860
5861 // stylus
5862 processKey(mapper, BTN_TOOL_RUBBER, 0);
5863 processKey(mapper, BTN_TOOL_PEN, 1);
5864 processSync(mapper);
5865 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5866 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005867 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005868
5869 // brush
5870 processKey(mapper, BTN_TOOL_PEN, 0);
5871 processKey(mapper, BTN_TOOL_BRUSH, 1);
5872 processSync(mapper);
5873 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5874 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005875 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005876
5877 // pencil
5878 processKey(mapper, BTN_TOOL_BRUSH, 0);
5879 processKey(mapper, BTN_TOOL_PENCIL, 1);
5880 processSync(mapper);
5881 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5882 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005883 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005884
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08005885 // air-brush
Michael Wrightd02c5b62014-02-10 15:10:22 -08005886 processKey(mapper, BTN_TOOL_PENCIL, 0);
5887 processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
5888 processSync(mapper);
5889 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5890 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005891 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005892
5893 // mouse
5894 processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
5895 processKey(mapper, BTN_TOOL_MOUSE, 1);
5896 processSync(mapper);
5897 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5898 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005899 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005900
5901 // lens
5902 processKey(mapper, BTN_TOOL_MOUSE, 0);
5903 processKey(mapper, BTN_TOOL_LENS, 1);
5904 processSync(mapper);
5905 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5906 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005907 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005908
5909 // double-tap
5910 processKey(mapper, BTN_TOOL_LENS, 0);
5911 processKey(mapper, BTN_TOOL_DOUBLETAP, 1);
5912 processSync(mapper);
5913 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5914 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005915 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005916
5917 // triple-tap
5918 processKey(mapper, BTN_TOOL_DOUBLETAP, 0);
5919 processKey(mapper, BTN_TOOL_TRIPLETAP, 1);
5920 processSync(mapper);
5921 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5922 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005923 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005924
5925 // quad-tap
5926 processKey(mapper, BTN_TOOL_TRIPLETAP, 0);
5927 processKey(mapper, BTN_TOOL_QUADTAP, 1);
5928 processSync(mapper);
5929 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5930 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005931 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005932
5933 // finger
5934 processKey(mapper, BTN_TOOL_QUADTAP, 0);
5935 processKey(mapper, BTN_TOOL_FINGER, 1);
5936 processSync(mapper);
5937 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5938 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005939 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005940
5941 // stylus trumps finger
5942 processKey(mapper, BTN_TOOL_PEN, 1);
5943 processSync(mapper);
5944 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5945 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005946 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005947
5948 // eraser trumps stylus
5949 processKey(mapper, BTN_TOOL_RUBBER, 1);
5950 processSync(mapper);
5951 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5952 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005953 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005954
5955 // mouse trumps eraser
5956 processKey(mapper, BTN_TOOL_MOUSE, 1);
5957 processSync(mapper);
5958 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5959 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005960 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005961
5962 // back to default tool type
5963 processKey(mapper, BTN_TOOL_MOUSE, 0);
5964 processKey(mapper, BTN_TOOL_RUBBER, 0);
5965 processKey(mapper, BTN_TOOL_PEN, 0);
5966 processKey(mapper, BTN_TOOL_FINGER, 0);
5967 processSync(mapper);
5968 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5969 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005970 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005971}
5972
5973TEST_F(SingleTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005974 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005975 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005976 prepareButtons();
5977 prepareAxes(POSITION);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08005978 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_FINGER, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005979 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005980
5981 NotifyMotionArgs motionArgs;
5982
5983 // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0
5984 processKey(mapper, BTN_TOOL_FINGER, 1);
5985 processMove(mapper, 100, 200);
5986 processSync(mapper);
5987 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5988 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5989 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5990 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5991
5992 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5993 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5994 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5995 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5996
5997 // move a little
5998 processMove(mapper, 150, 250);
5999 processSync(mapper);
6000 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6001 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
6002 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6003 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6004
6005 // down when BTN_TOUCH is pressed, pressure defaults to 1
6006 processKey(mapper, BTN_TOUCH, 1);
6007 processSync(mapper);
6008 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6009 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
6010 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6011 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6012
6013 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6014 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6015 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6016 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
6017
6018 // up when BTN_TOUCH is released, hover restored
6019 processKey(mapper, BTN_TOUCH, 0);
6020 processSync(mapper);
6021 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6022 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
6023 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6024 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
6025
6026 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6027 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
6028 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6029 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6030
6031 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6032 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
6033 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6034 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6035
6036 // exit hover when pointer goes away
6037 processKey(mapper, BTN_TOOL_FINGER, 0);
6038 processSync(mapper);
6039 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6040 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
6041 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6042 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6043}
6044
6045TEST_F(SingleTouchInputMapperTest, Process_WhenAbsPressureIsPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006046 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006047 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006048 prepareButtons();
6049 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00006050 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08006051
6052 NotifyMotionArgs motionArgs;
6053
6054 // initially hovering because pressure is 0
6055 processDown(mapper, 100, 200);
6056 processPressure(mapper, 0);
6057 processSync(mapper);
6058 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6059 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
6060 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6061 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
6062
6063 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6064 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
6065 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6066 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
6067
6068 // move a little
6069 processMove(mapper, 150, 250);
6070 processSync(mapper);
6071 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6072 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
6073 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6074 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6075
6076 // down when pressure is non-zero
6077 processPressure(mapper, RAW_PRESSURE_MAX);
6078 processSync(mapper);
6079 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6080 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
6081 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6082 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6083
6084 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6085 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6086 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6087 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
6088
6089 // up when pressure becomes 0, hover restored
6090 processPressure(mapper, 0);
6091 processSync(mapper);
6092 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6093 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
6094 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6095 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
6096
6097 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6098 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
6099 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6100 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6101
6102 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6103 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
6104 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6105 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6106
6107 // exit hover when pointer goes away
6108 processUp(mapper);
6109 processSync(mapper);
6110 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6111 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
6112 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6113 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6114}
6115
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006116TEST_F(SingleTouchInputMapperTest, Reset_CancelsOngoingGesture) {
6117 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006118 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006119 prepareButtons();
6120 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00006121 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006122
6123 // Touch down.
6124 processDown(mapper, 100, 200);
6125 processPressure(mapper, 1);
6126 processSync(mapper);
6127 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6128 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
6129
6130 // Reset the mapper. This should cancel the ongoing gesture.
6131 resetMapper(mapper, ARBITRARY_TIME);
6132 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6133 WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
6134
6135 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6136}
6137
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006138TEST_F(SingleTouchInputMapperTest, Reset_RecreatesTouchState) {
6139 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006140 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006141 prepareButtons();
6142 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00006143 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006144
6145 // Set the initial state for the touch pointer.
6146 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_X, 100);
6147 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_Y, 200);
6148 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_PRESSURE, RAW_PRESSURE_MAX);
6149 mFakeEventHub->setScanCodeState(EVENTHUB_ID, BTN_TOUCH, 1);
6150
6151 // Reset the mapper. When the mapper is reset, we expect it to attempt to recreate the touch
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006152 // state by reading the current axis values. Since there was no ongoing gesture, calling reset
6153 // does not generate any events.
6154 resetMapper(mapper, ARBITRARY_TIME);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006155
6156 // Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
6157 // the recreated touch state to generate a down event.
6158 processSync(mapper);
6159 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6160 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPressure(1.f))));
6161
6162 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6163}
6164
lilinnan687e58f2022-07-19 16:00:50 +08006165TEST_F(SingleTouchInputMapperTest,
6166 Process_WhenViewportDisplayIdChanged_TouchIsCanceledAndDeviceIsReset) {
6167 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006168 prepareDisplay(ui::ROTATION_0);
lilinnan687e58f2022-07-19 16:00:50 +08006169 prepareButtons();
6170 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006171 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
lilinnan687e58f2022-07-19 16:00:50 +08006172 NotifyMotionArgs motionArgs;
6173
6174 // Down.
Prabir Pradhan3e5ec702022-07-29 16:26:24 +00006175 processDown(mapper, 100, 200);
lilinnan687e58f2022-07-19 16:00:50 +08006176 processSync(mapper);
6177
6178 // We should receive a down event
6179 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6180 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6181
6182 // Change display id
6183 clearViewports();
6184 prepareSecondaryDisplay(ViewportType::INTERNAL);
6185
6186 // We should receive a cancel event
6187 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6188 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
6189 // Then receive reset called
6190 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6191}
6192
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006193TEST_F(SingleTouchInputMapperTest,
6194 Process_WhenViewportActiveStatusChanged_TouchIsCanceledAndDeviceIsReset) {
6195 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006196 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006197 prepareButtons();
6198 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006199 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006200 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6201 NotifyMotionArgs motionArgs;
6202
6203 // Start a new gesture.
6204 processDown(mapper, 100, 200);
6205 processSync(mapper);
6206 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6207 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6208
6209 // Make the viewport inactive. This will put the device in disabled mode.
6210 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6211 viewport->isActive = false;
6212 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006213 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006214
6215 // We should receive a cancel event for the ongoing gesture.
6216 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6217 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
6218 // Then we should be notified that the device was reset.
6219 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6220
6221 // No events are generated while the viewport is inactive.
6222 processMove(mapper, 101, 201);
6223 processSync(mapper);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006224 processUp(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006225 processSync(mapper);
6226 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6227
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006228 // Start a new gesture while the viewport is still inactive.
6229 processDown(mapper, 300, 400);
6230 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_X, 300);
6231 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_Y, 400);
6232 mFakeEventHub->setScanCodeState(EVENTHUB_ID, BTN_TOUCH, 1);
6233 processSync(mapper);
6234
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006235 // Make the viewport active again. The device should resume processing events.
6236 viewport->isActive = true;
6237 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006238 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006239
6240 // The device is reset because it changes back to direct mode, without generating any events.
6241 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6242 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6243
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006244 // In the next sync, the touch state that was recreated when the device was reset is reported.
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006245 processSync(mapper);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006246 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6247 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006248
6249 // No more events.
6250 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6251 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
6252}
6253
Prabir Pradhan211ba622022-10-31 21:09:21 +00006254TEST_F(SingleTouchInputMapperTest, ButtonIsReleasedOnTouchUp) {
6255 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006256 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan211ba622022-10-31 21:09:21 +00006257 prepareButtons();
6258 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006259 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan211ba622022-10-31 21:09:21 +00006260 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6261
6262 // Press a stylus button.
6263 processKey(mapper, BTN_STYLUS, 1);
6264 processSync(mapper);
6265
6266 // Start a touch gesture and ensure the BUTTON_PRESS event is generated.
6267 processDown(mapper, 100, 200);
6268 processSync(mapper);
6269 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6270 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6271 WithCoords(toDisplayX(100), toDisplayY(200)),
6272 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6273 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6274 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
6275 WithCoords(toDisplayX(100), toDisplayY(200)),
6276 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6277
6278 // Release the touch gesture. Ensure that the BUTTON_RELEASE event is generated even though
6279 // the button has not actually been released, since there will be no pointers through which the
6280 // button state can be reported. The event is generated at the location of the pointer before
6281 // it went up.
6282 processUp(mapper);
6283 processSync(mapper);
6284 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6285 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
6286 WithCoords(toDisplayX(100), toDisplayY(200)), WithButtonState(0))));
6287 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6288 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6289 WithCoords(toDisplayX(100), toDisplayY(200)), WithButtonState(0))));
6290}
6291
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00006292TEST_F(SingleTouchInputMapperTest, StylusButtonMotionEventsDisabled) {
6293 addConfigurationProperty("touch.deviceType", "touchScreen");
6294 prepareDisplay(ui::ROTATION_0);
6295 prepareButtons();
6296 prepareAxes(POSITION);
6297
6298 mFakePolicy->setStylusButtonMotionEventsEnabled(false);
6299
Arpit Singha8c236b2023-04-25 13:56:05 +00006300 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00006301 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6302
6303 // Press a stylus button.
6304 processKey(mapper, BTN_STYLUS, 1);
6305 processSync(mapper);
6306
6307 // Start a touch gesture and ensure that the stylus button is not reported.
6308 processDown(mapper, 100, 200);
6309 processSync(mapper);
6310 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6311 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithButtonState(0))));
6312
6313 // Release and press the stylus button again.
6314 processKey(mapper, BTN_STYLUS, 0);
6315 processSync(mapper);
6316 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6317 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
6318 processKey(mapper, BTN_STYLUS, 1);
6319 processSync(mapper);
6320 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6321 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
6322
6323 // Release the touch gesture.
6324 processUp(mapper);
6325 processSync(mapper);
6326 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6327 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
6328
6329 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6330}
6331
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006332TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsSetToTouchNavigation_setsCorrectType) {
6333 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
6334 prepareDisplay(ui::ROTATION_0);
6335 prepareButtons();
6336 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006337 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006338 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6339
6340 ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION, mapper.getSources());
6341}
6342
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006343TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsChangedToTouchNavigation_updatesDeviceType) {
6344 // Initialize the device without setting device source to touch navigation.
6345 addConfigurationProperty("touch.deviceType", "touchScreen");
6346 prepareDisplay(ui::ROTATION_0);
6347 prepareButtons();
6348 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006349 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006350
6351 // Ensure that the device is created as a touchscreen, not touch navigation.
6352 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
6353
6354 // Add device type association after the device was created.
6355 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
6356
6357 // Send update to the mapper.
6358 std::list<NotifyArgs> unused2 =
6359 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006360 InputReaderConfiguration::Change::DEVICE_TYPE /*changes*/);
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006361
6362 // Check whether device type update was successful.
6363 ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION, mDevice->getSources());
6364}
6365
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006366TEST_F(SingleTouchInputMapperTest, HoverEventsOutsidePhysicalFrameAreIgnored) {
6367 // Initialize the device without setting device source to touch navigation.
6368 addConfigurationProperty("touch.deviceType", "touchScreen");
6369 prepareDisplay(ui::ROTATION_0);
6370 prepareButtons();
6371 prepareAxes(POSITION);
6372 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
6373
6374 // Set a physical frame in the display viewport.
6375 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6376 viewport->physicalLeft = 0;
6377 viewport->physicalTop = 0;
6378 viewport->physicalRight = DISPLAY_WIDTH / 2;
6379 viewport->physicalBottom = DISPLAY_HEIGHT / 2;
6380 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006381 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006382
Arpit Singha8c236b2023-04-25 13:56:05 +00006383 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006384
6385 // Hovering inside the physical frame produces events.
6386 processKey(mapper, BTN_TOOL_PEN, 1);
6387 processMove(mapper, RAW_X_MIN + 1, RAW_Y_MIN + 1);
6388 processSync(mapper);
6389 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6390 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)));
6391 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6392 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)));
6393
6394 // Leaving the physical frame ends the hovering gesture.
6395 processMove(mapper, RAW_X_MAX - 1, RAW_Y_MAX - 1);
6396 processSync(mapper);
6397 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6398 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT)));
6399
6400 // Moving outside the physical frame does not produce events.
6401 processMove(mapper, RAW_X_MAX - 2, RAW_Y_MAX - 2);
6402 processSync(mapper);
6403 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6404
6405 // Re-entering the physical frame produces events.
6406 processMove(mapper, RAW_X_MIN, RAW_Y_MIN);
6407 processSync(mapper);
6408 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6409 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)));
6410 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6411 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)));
6412}
6413
Prabir Pradhan5632d622021-09-06 07:57:20 -07006414// --- TouchDisplayProjectionTest ---
6415
6416class TouchDisplayProjectionTest : public SingleTouchInputMapperTest {
6417public:
6418 // The values inside DisplayViewport are expected to be pre-rotated. This updates the current
6419 // DisplayViewport to pre-rotate the values. The viewport's physical display will be set to the
6420 // rotated equivalent of the given un-rotated physical display bounds.
Prabir Pradhana9df3162022-12-05 23:57:27 +00006421 void configurePhysicalDisplay(ui::Rotation orientation, Rect naturalPhysicalDisplay,
6422 int32_t naturalDisplayWidth = DISPLAY_WIDTH,
6423 int32_t naturalDisplayHeight = DISPLAY_HEIGHT) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006424 uint32_t inverseRotationFlags;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006425 auto rotatedWidth = naturalDisplayWidth;
6426 auto rotatedHeight = naturalDisplayHeight;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006427 switch (orientation) {
Michael Wrighta9cf4192022-12-01 23:46:39 +00006428 case ui::ROTATION_90:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006429 inverseRotationFlags = ui::Transform::ROT_270;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006430 std::swap(rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006431 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006432 case ui::ROTATION_180:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006433 inverseRotationFlags = ui::Transform::ROT_180;
6434 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006435 case ui::ROTATION_270:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006436 inverseRotationFlags = ui::Transform::ROT_90;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006437 std::swap(rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006438 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006439 case ui::ROTATION_0:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006440 inverseRotationFlags = ui::Transform::ROT_0;
6441 break;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006442 }
6443
Prabir Pradhana9df3162022-12-05 23:57:27 +00006444 const ui::Transform rotation(inverseRotationFlags, rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006445 const Rect rotatedPhysicalDisplay = rotation.transform(naturalPhysicalDisplay);
6446
6447 std::optional<DisplayViewport> internalViewport =
6448 *mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6449 DisplayViewport& v = *internalViewport;
6450 v.displayId = DISPLAY_ID;
6451 v.orientation = orientation;
6452
6453 v.logicalLeft = 0;
6454 v.logicalTop = 0;
6455 v.logicalRight = 100;
6456 v.logicalBottom = 100;
6457
6458 v.physicalLeft = rotatedPhysicalDisplay.left;
6459 v.physicalTop = rotatedPhysicalDisplay.top;
6460 v.physicalRight = rotatedPhysicalDisplay.right;
6461 v.physicalBottom = rotatedPhysicalDisplay.bottom;
6462
Prabir Pradhana9df3162022-12-05 23:57:27 +00006463 v.deviceWidth = rotatedWidth;
6464 v.deviceHeight = rotatedHeight;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006465
6466 v.isActive = true;
6467 v.uniqueId = UNIQUE_ID;
6468 v.type = ViewportType::INTERNAL;
6469 mFakePolicy->updateViewport(v);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006470 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006471 }
6472
6473 void assertReceivedMove(const Point& point) {
6474 NotifyMotionArgs motionArgs;
6475 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6476 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006477 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Prabir Pradhan5632d622021-09-06 07:57:20 -07006478 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], point.x, point.y,
6479 1, 0, 0, 0, 0, 0, 0, 0));
6480 }
6481};
6482
6483TEST_F(TouchDisplayProjectionTest, IgnoresTouchesOutsidePhysicalDisplay) {
6484 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006485 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006486
6487 prepareButtons();
6488 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006489 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan5632d622021-09-06 07:57:20 -07006490
6491 NotifyMotionArgs motionArgs;
6492
6493 // Configure the DisplayViewport such that the logical display maps to a subsection of
6494 // the display panel called the physical display. Here, the physical display is bounded by the
6495 // points (10, 20) and (70, 160) inside the display space, which is of the size 400 x 800.
6496 static const Rect kPhysicalDisplay{10, 20, 70, 160};
6497 static const std::array<Point, 6> kPointsOutsidePhysicalDisplay{
6498 {{-10, -10}, {0, 0}, {5, 100}, {50, 15}, {75, 100}, {50, 165}}};
6499
Michael Wrighta9cf4192022-12-01 23:46:39 +00006500 for (auto orientation : {ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180, ui::ROTATION_270}) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006501 configurePhysicalDisplay(orientation, kPhysicalDisplay);
6502
6503 // Touches outside the physical display should be ignored, and should not generate any
6504 // events. Ensure touches at the following points that lie outside of the physical display
6505 // area do not generate any events.
6506 for (const auto& point : kPointsOutsidePhysicalDisplay) {
6507 processDown(mapper, toRawX(point.x), toRawY(point.y));
6508 processSync(mapper);
6509 processUp(mapper);
6510 processSync(mapper);
6511 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled())
6512 << "Unexpected event generated for touch outside physical display at point: "
6513 << point.x << ", " << point.y;
6514 }
6515 }
6516}
6517
6518TEST_F(TouchDisplayProjectionTest, EmitsTouchDownAfterEnteringPhysicalDisplay) {
6519 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006520 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006521
6522 prepareButtons();
6523 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006524 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan5632d622021-09-06 07:57:20 -07006525
6526 NotifyMotionArgs motionArgs;
6527
6528 // Configure the DisplayViewport such that the logical display maps to a subsection of
6529 // the display panel called the physical display. Here, the physical display is bounded by the
6530 // points (10, 20) and (70, 160) inside the display space, which is of the size 400 x 800.
6531 static const Rect kPhysicalDisplay{10, 20, 70, 160};
6532
Michael Wrighta9cf4192022-12-01 23:46:39 +00006533 for (auto orientation : {ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180, ui::ROTATION_270}) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006534 configurePhysicalDisplay(orientation, kPhysicalDisplay);
6535
6536 // Touches that start outside the physical display should be ignored until it enters the
6537 // physical display bounds, at which point it should generate a down event. Start a touch at
6538 // the point (5, 100), which is outside the physical display bounds.
6539 static const Point kOutsidePoint{5, 100};
6540 processDown(mapper, toRawX(kOutsidePoint.x), toRawY(kOutsidePoint.y));
6541 processSync(mapper);
6542 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6543
6544 // Move the touch into the physical display area. This should generate a pointer down.
6545 processMove(mapper, toRawX(11), toRawY(21));
6546 processSync(mapper);
6547 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6548 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006549 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Prabir Pradhan5632d622021-09-06 07:57:20 -07006550 ASSERT_NO_FATAL_FAILURE(
6551 assertPointerCoords(motionArgs.pointerCoords[0], 11, 21, 1, 0, 0, 0, 0, 0, 0, 0));
6552
6553 // Move the touch inside the physical display area. This should generate a pointer move.
6554 processMove(mapper, toRawX(69), toRawY(159));
6555 processSync(mapper);
6556 assertReceivedMove({69, 159});
6557
6558 // Move outside the physical display area. Since the pointer is already down, this should
6559 // now continue generating events.
6560 processMove(mapper, toRawX(kOutsidePoint.x), toRawY(kOutsidePoint.y));
6561 processSync(mapper);
6562 assertReceivedMove(kOutsidePoint);
6563
6564 // Release. This should generate a pointer up.
6565 processUp(mapper);
6566 processSync(mapper);
6567 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6568 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
6569 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], kOutsidePoint.x,
6570 kOutsidePoint.y, 1, 0, 0, 0, 0, 0, 0, 0));
6571
6572 // Ensure no more events were generated.
6573 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
6574 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6575 }
6576}
6577
Prabir Pradhana9df3162022-12-05 23:57:27 +00006578// --- TouchscreenPrecisionTests ---
6579
6580// This test suite is used to ensure that touchscreen devices are scaled and configured correctly
6581// in various orientations and with different display rotations. We configure the touchscreen to
6582// have a higher resolution than that of the display by an integer scale factor in each axis so that
6583// we can enforce that coordinates match precisely as expected.
6584class TouchscreenPrecisionTestsFixture : public TouchDisplayProjectionTest,
6585 public ::testing::WithParamInterface<ui::Rotation> {
6586public:
6587 void SetUp() override {
6588 SingleTouchInputMapperTest::SetUp();
6589
6590 // Prepare the raw axes to have twice the resolution of the display in the X axis and
6591 // four times the resolution of the display in the Y axis.
6592 prepareButtons();
6593 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, PRECISION_RAW_X_MIN, PRECISION_RAW_X_MAX,
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006594 PRECISION_RAW_X_FLAT, PRECISION_RAW_X_FUZZ,
6595 PRECISION_RAW_X_RES);
Prabir Pradhana9df3162022-12-05 23:57:27 +00006596 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, PRECISION_RAW_Y_MIN, PRECISION_RAW_Y_MAX,
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006597 PRECISION_RAW_Y_FLAT, PRECISION_RAW_Y_FUZZ,
6598 PRECISION_RAW_Y_RES);
Prabir Pradhana9df3162022-12-05 23:57:27 +00006599 }
6600
6601 static const int32_t PRECISION_RAW_X_MIN = TouchInputMapperTest::RAW_X_MIN;
6602 static const int32_t PRECISION_RAW_X_MAX = PRECISION_RAW_X_MIN + DISPLAY_WIDTH * 2 - 1;
6603 static const int32_t PRECISION_RAW_Y_MIN = TouchInputMapperTest::RAW_Y_MIN;
6604 static const int32_t PRECISION_RAW_Y_MAX = PRECISION_RAW_Y_MIN + DISPLAY_HEIGHT * 4 - 1;
6605
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006606 static const int32_t PRECISION_RAW_X_RES = 50; // units per millimeter
6607 static const int32_t PRECISION_RAW_Y_RES = 100; // units per millimeter
6608
6609 static const int32_t PRECISION_RAW_X_FLAT = 16;
6610 static const int32_t PRECISION_RAW_Y_FLAT = 32;
6611
6612 static const int32_t PRECISION_RAW_X_FUZZ = 4;
6613 static const int32_t PRECISION_RAW_Y_FUZZ = 8;
6614
Prabir Pradhana9df3162022-12-05 23:57:27 +00006615 static const std::array<Point, 4> kRawCorners;
6616};
6617
6618const std::array<Point, 4> TouchscreenPrecisionTestsFixture::kRawCorners = {{
6619 {PRECISION_RAW_X_MIN, PRECISION_RAW_Y_MIN}, // left-top
6620 {PRECISION_RAW_X_MAX, PRECISION_RAW_Y_MIN}, // right-top
6621 {PRECISION_RAW_X_MAX, PRECISION_RAW_Y_MAX}, // right-bottom
6622 {PRECISION_RAW_X_MIN, PRECISION_RAW_Y_MAX}, // left-bottom
6623}};
6624
6625// Tests for how the touchscreen is oriented relative to the natural orientation of the display.
6626// For example, if a touchscreen is configured with an orientation of 90 degrees, it is a portrait
6627// touchscreen panel that is used on a device whose natural display orientation is in landscape.
6628TEST_P(TouchscreenPrecisionTestsFixture, OrientationPrecision) {
6629 enum class Orientation {
6630 ORIENTATION_0 = ui::toRotationInt(ui::ROTATION_0),
6631 ORIENTATION_90 = ui::toRotationInt(ui::ROTATION_90),
6632 ORIENTATION_180 = ui::toRotationInt(ui::ROTATION_180),
6633 ORIENTATION_270 = ui::toRotationInt(ui::ROTATION_270),
6634 ftl_last = ORIENTATION_270,
6635 };
6636 using Orientation::ORIENTATION_0, Orientation::ORIENTATION_90, Orientation::ORIENTATION_180,
6637 Orientation::ORIENTATION_270;
6638 static const std::map<Orientation, std::array<vec2, 4> /*mappedCorners*/> kMappedCorners = {
6639 {ORIENTATION_0, {{{0, 0}, {479.5, 0}, {479.5, 799.75}, {0, 799.75}}}},
6640 {ORIENTATION_90, {{{0, 479.5}, {0, 0}, {799.75, 0}, {799.75, 479.5}}}},
6641 {ORIENTATION_180, {{{479.5, 799.75}, {0, 799.75}, {0, 0}, {479.5, 0}}}},
6642 {ORIENTATION_270, {{{799.75, 0}, {799.75, 479.5}, {0, 479.5}, {0, 0}}}},
6643 };
6644
6645 const auto touchscreenOrientation = static_cast<Orientation>(ui::toRotationInt(GetParam()));
6646
6647 // Configure the touchscreen as being installed in the one of the four different orientations
6648 // relative to the display.
6649 addConfigurationProperty("touch.deviceType", "touchScreen");
6650 addConfigurationProperty("touch.orientation", ftl::enum_string(touchscreenOrientation).c_str());
6651 prepareDisplay(ui::ROTATION_0);
6652
Arpit Singha8c236b2023-04-25 13:56:05 +00006653 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhana9df3162022-12-05 23:57:27 +00006654
6655 // If the touchscreen is installed in a rotated orientation relative to the display (i.e. in
6656 // orientations of either 90 or 270) this means the display's natural resolution will be
6657 // flipped.
6658 const bool displayRotated =
6659 touchscreenOrientation == ORIENTATION_90 || touchscreenOrientation == ORIENTATION_270;
6660 const int32_t width = displayRotated ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
6661 const int32_t height = displayRotated ? DISPLAY_WIDTH : DISPLAY_HEIGHT;
6662 const Rect physicalFrame{0, 0, width, height};
6663 configurePhysicalDisplay(ui::ROTATION_0, physicalFrame, width, height);
6664
6665 const auto& expectedPoints = kMappedCorners.at(touchscreenOrientation);
6666 const float expectedPrecisionX = displayRotated ? 4 : 2;
6667 const float expectedPrecisionY = displayRotated ? 2 : 4;
6668
6669 // Test all four corners.
6670 for (int i = 0; i < 4; i++) {
6671 const auto& raw = kRawCorners[i];
6672 processDown(mapper, raw.x, raw.y);
6673 processSync(mapper);
6674 const auto& expected = expectedPoints[i];
6675 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6676 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6677 WithCoords(expected.x, expected.y),
6678 WithPrecision(expectedPrecisionX, expectedPrecisionY))))
6679 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6680 << "with touchscreen orientation "
6681 << ftl::enum_string(touchscreenOrientation).c_str() << ", expected point ("
6682 << 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 Pradhan82687402022-12-06 01:32:53 +00006691TEST_P(TouchscreenPrecisionTestsFixture, RotationPrecisionWhenOrientationAware) {
6692 static const std::map<ui::Rotation /*rotation*/, std::array<vec2, 4> /*mappedCorners*/>
6693 kMappedCorners = {
6694 {ui::ROTATION_0, {{{0, 0}, {479.5, 0}, {479.5, 799.75}, {0, 799.75}}}},
6695 {ui::ROTATION_90, {{{0.5, 0}, {480, 0}, {480, 799.75}, {0.5, 799.75}}}},
6696 {ui::ROTATION_180, {{{0.5, 0.25}, {480, 0.25}, {480, 800}, {0.5, 800}}}},
6697 {ui::ROTATION_270, {{{0, 0.25}, {479.5, 0.25}, {479.5, 800}, {0, 800}}}},
6698 };
6699
6700 const ui::Rotation displayRotation = GetParam();
6701
6702 addConfigurationProperty("touch.deviceType", "touchScreen");
6703 prepareDisplay(displayRotation);
6704
Arpit Singha8c236b2023-04-25 13:56:05 +00006705 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan82687402022-12-06 01:32:53 +00006706
6707 const auto& expectedPoints = kMappedCorners.at(displayRotation);
6708
6709 // Test all four corners.
6710 for (int i = 0; i < 4; i++) {
6711 const auto& expected = expectedPoints[i];
6712 const auto& raw = kRawCorners[i];
6713 processDown(mapper, raw.x, raw.y);
6714 processSync(mapper);
6715 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6716 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6717 WithCoords(expected.x, expected.y), WithPrecision(2, 4))))
6718 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6719 << "with display rotation " << ui::toCString(displayRotation)
6720 << ", expected point (" << expected.x << ", " << expected.y << ").";
6721 processUp(mapper);
6722 processSync(mapper);
6723 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6724 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6725 WithCoords(expected.x, expected.y))));
6726 }
6727}
6728
Prabir Pradhan3e798762022-12-02 21:02:11 +00006729TEST_P(TouchscreenPrecisionTestsFixture, RotationPrecisionOrientationAwareInOri270) {
6730 static const std::map<ui::Rotation /*orientation*/, std::array<vec2, 4> /*mappedCorners*/>
6731 kMappedCorners = {
6732 {ui::ROTATION_0, {{{799.75, 0}, {799.75, 479.5}, {0, 479.5}, {0, 0}}}},
6733 {ui::ROTATION_90, {{{800, 0}, {800, 479.5}, {0.25, 479.5}, {0.25, 0}}}},
6734 {ui::ROTATION_180, {{{800, 0.5}, {800, 480}, {0.25, 480}, {0.25, 0.5}}}},
6735 {ui::ROTATION_270, {{{799.75, 0.5}, {799.75, 480}, {0, 480}, {0, 0.5}}}},
6736 };
6737
6738 const ui::Rotation displayRotation = GetParam();
6739
6740 addConfigurationProperty("touch.deviceType", "touchScreen");
6741 addConfigurationProperty("touch.orientation", "ORIENTATION_270");
6742
Arpit Singha8c236b2023-04-25 13:56:05 +00006743 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan3e798762022-12-02 21:02:11 +00006744
6745 // Ori 270, so width and height swapped
6746 const Rect physicalFrame{0, 0, DISPLAY_HEIGHT, DISPLAY_WIDTH};
6747 prepareDisplay(displayRotation);
6748 configurePhysicalDisplay(displayRotation, physicalFrame, DISPLAY_HEIGHT, DISPLAY_WIDTH);
6749
6750 const auto& expectedPoints = kMappedCorners.at(displayRotation);
6751
6752 // Test all four corners.
6753 for (int i = 0; i < 4; i++) {
6754 const auto& expected = expectedPoints[i];
6755 const auto& raw = kRawCorners[i];
6756 processDown(mapper, raw.x, raw.y);
6757 processSync(mapper);
6758 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6759 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6760 WithCoords(expected.x, expected.y), WithPrecision(4, 2))))
6761 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6762 << "with display rotation " << ui::toCString(displayRotation)
6763 << ", expected point (" << expected.x << ", " << expected.y << ").";
6764 processUp(mapper);
6765 processSync(mapper);
6766 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6767 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6768 WithCoords(expected.x, expected.y))));
6769 }
6770}
6771
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006772TEST_P(TouchscreenPrecisionTestsFixture, MotionRangesAreOrientedInRotatedDisplay) {
6773 const ui::Rotation displayRotation = GetParam();
6774
6775 addConfigurationProperty("touch.deviceType", "touchScreen");
6776 prepareDisplay(displayRotation);
6777
6778 __attribute__((unused)) SingleTouchInputMapper& mapper =
Arpit Singha8c236b2023-04-25 13:56:05 +00006779 constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006780
6781 const InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
6782 // MotionRanges use display pixels as their units
6783 const auto* xRange = deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHSCREEN);
6784 const auto* yRange = deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_Y, AINPUT_SOURCE_TOUCHSCREEN);
6785
6786 // The MotionRanges should be oriented in the rotated display's coordinate space
6787 const bool displayRotated =
6788 displayRotation == ui::ROTATION_90 || displayRotation == ui::ROTATION_270;
6789
6790 constexpr float MAX_X = 479.5;
6791 constexpr float MAX_Y = 799.75;
6792 EXPECT_EQ(xRange->min, 0.f);
6793 EXPECT_EQ(yRange->min, 0.f);
6794 EXPECT_EQ(xRange->max, displayRotated ? MAX_Y : MAX_X);
6795 EXPECT_EQ(yRange->max, displayRotated ? MAX_X : MAX_Y);
6796
6797 EXPECT_EQ(xRange->flat, 8.f);
6798 EXPECT_EQ(yRange->flat, 8.f);
6799
6800 EXPECT_EQ(xRange->fuzz, 2.f);
6801 EXPECT_EQ(yRange->fuzz, 2.f);
6802
6803 EXPECT_EQ(xRange->resolution, 25.f); // pixels per millimeter
6804 EXPECT_EQ(yRange->resolution, 25.f); // pixels per millimeter
6805}
6806
Prabir Pradhana9df3162022-12-05 23:57:27 +00006807// Run the precision tests for all rotations.
6808INSTANTIATE_TEST_SUITE_P(TouchscreenPrecisionTests, TouchscreenPrecisionTestsFixture,
6809 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
6810 ui::ROTATION_270),
6811 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
6812 return ftl::enum_string(testParamInfo.param);
6813 });
6814
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006815// --- ExternalStylusFusionTest ---
6816
6817class ExternalStylusFusionTest : public SingleTouchInputMapperTest {
6818public:
6819 SingleTouchInputMapper& initializeInputMapperWithExternalStylus() {
6820 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006821 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006822 prepareButtons();
6823 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006824 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006825
6826 mStylusState.when = ARBITRARY_TIME;
6827 mStylusState.pressure = 0.f;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006828 mStylusState.toolType = ToolType::STYLUS;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006829 mReader->getContext()->setExternalStylusDevices({mExternalStylusDeviceInfo});
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006830 configureDevice(InputReaderConfiguration::Change::EXTERNAL_STYLUS_PRESENCE);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006831 processExternalStylusState(mapper);
6832 return mapper;
6833 }
6834
6835 std::list<NotifyArgs> processExternalStylusState(InputMapper& mapper) {
6836 std::list<NotifyArgs> generatedArgs = mapper.updateExternalStylusState(mStylusState);
6837 for (const NotifyArgs& args : generatedArgs) {
6838 mFakeListener->notify(args);
6839 }
6840 // Loop the reader to flush the input listener queue.
6841 mReader->loopOnce();
6842 return generatedArgs;
6843 }
6844
6845protected:
6846 StylusState mStylusState{};
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006847
6848 void testStartFusedStylusGesture(SingleTouchInputMapper& mapper) {
6849 auto toolTypeSource =
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006850 AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006851
6852 // The first pointer is withheld.
6853 processDown(mapper, 100, 200);
6854 processSync(mapper);
6855 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6856 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6857 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6858
6859 // The external stylus reports pressure. The withheld finger pointer is released as a
6860 // stylus.
6861 mStylusState.pressure = 1.f;
6862 processExternalStylusState(mapper);
6863 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6864 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6865 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6866
6867 // Subsequent pointer events are not withheld.
6868 processMove(mapper, 101, 201);
6869 processSync(mapper);
6870 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6871 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6872
6873 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6874 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6875 }
6876
6877 void testSuccessfulFusionGesture(SingleTouchInputMapper& mapper) {
6878 ASSERT_NO_FATAL_FAILURE(testStartFusedStylusGesture(mapper));
6879
6880 // Releasing the touch pointer ends the gesture.
6881 processUp(mapper);
6882 processSync(mapper);
6883 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006884 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(STYLUS_FUSION_SOURCE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006885 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006886
6887 mStylusState.pressure = 0.f;
6888 processExternalStylusState(mapper);
6889 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6890 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6891 }
6892
6893 void testUnsuccessfulFusionGesture(SingleTouchInputMapper& mapper) {
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006894 // When stylus fusion is not successful, events should be reported with the original source.
6895 // In this case, it is from a touchscreen.
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006896 auto toolTypeSource =
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006897 AllOf(WithSource(AINPUT_SOURCE_TOUCHSCREEN), WithToolType(ToolType::FINGER));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006898
6899 // The first pointer is withheld when an external stylus is connected,
6900 // and a timeout is requested.
6901 processDown(mapper, 100, 200);
6902 processSync(mapper);
6903 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6904 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6905 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6906
6907 // If the timeout expires early, it is requested again.
6908 handleTimeout(mapper, ARBITRARY_TIME + 1);
6909 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6910 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6911
6912 // When the timeout expires, the withheld touch is released as a finger pointer.
6913 handleTimeout(mapper, ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT);
6914 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6915 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6916
6917 // Subsequent pointer events are not withheld.
6918 processMove(mapper, 101, 201);
6919 processSync(mapper);
6920 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6921 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6922 processUp(mapper);
6923 processSync(mapper);
6924 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6925 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP))));
6926
6927 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6928 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6929 }
6930
6931private:
6932 InputDeviceInfo mExternalStylusDeviceInfo{};
6933};
6934
6935TEST_F(ExternalStylusFusionTest, UsesBluetoothStylusSource) {
6936 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006937 ASSERT_EQ(STYLUS_FUSION_SOURCE, mapper.getSources());
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006938}
6939
6940TEST_F(ExternalStylusFusionTest, UnsuccessfulFusion) {
6941 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6942 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6943}
6944
6945TEST_F(ExternalStylusFusionTest, SuccessfulFusion_TouchFirst) {
6946 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6947 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6948}
6949
6950// Test a successful stylus fusion gesture where the pressure is reported by the external
6951// before the touch is reported by the touchscreen.
6952TEST_F(ExternalStylusFusionTest, SuccessfulFusion_PressureFirst) {
6953 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006954 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006955
6956 // The external stylus reports pressure first. It is ignored for now.
6957 mStylusState.pressure = 1.f;
6958 processExternalStylusState(mapper);
6959 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6960 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6961
6962 // When the touch goes down afterwards, it is reported as a stylus pointer.
6963 processDown(mapper, 100, 200);
6964 processSync(mapper);
6965 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6966 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6967 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6968
6969 processMove(mapper, 101, 201);
6970 processSync(mapper);
6971 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6972 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6973 processUp(mapper);
6974 processSync(mapper);
6975 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6976 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP))));
6977
6978 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6979 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6980}
6981
6982TEST_F(ExternalStylusFusionTest, FusionIsRepeatedForEachNewGesture) {
6983 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6984
6985 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6986 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6987
6988 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6989 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6990 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6991 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6992}
6993
6994TEST_F(ExternalStylusFusionTest, FusedPointerReportsPressureChanges) {
6995 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006996 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006997
6998 mStylusState.pressure = 0.8f;
6999 processExternalStylusState(mapper);
7000 processDown(mapper, 100, 200);
7001 processSync(mapper);
7002 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7003 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
7004 WithPressure(0.8f))));
7005 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7006
7007 // The external stylus reports a pressure change. We wait for some time for a touch event.
7008 mStylusState.pressure = 0.6f;
7009 processExternalStylusState(mapper);
7010 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7011 ASSERT_NO_FATAL_FAILURE(
7012 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7013
7014 // If a touch is reported within the timeout, it reports the updated pressure.
7015 processMove(mapper, 101, 201);
7016 processSync(mapper);
7017 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7018 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
7019 WithPressure(0.6f))));
7020 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7021
7022 // There is another pressure change.
7023 mStylusState.pressure = 0.5f;
7024 processExternalStylusState(mapper);
7025 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7026 ASSERT_NO_FATAL_FAILURE(
7027 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7028
7029 // If a touch is not reported within the timeout, a move event is generated to report
7030 // the new pressure.
7031 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
7032 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7033 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
7034 WithPressure(0.5f))));
7035
7036 // If a zero pressure is reported before the touch goes up, the previous pressure value is
7037 // repeated indefinitely.
7038 mStylusState.pressure = 0.0f;
7039 processExternalStylusState(mapper);
7040 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7041 ASSERT_NO_FATAL_FAILURE(
7042 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7043 processMove(mapper, 102, 202);
7044 processSync(mapper);
7045 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7046 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
7047 WithPressure(0.5f))));
7048 processMove(mapper, 103, 203);
7049 processSync(mapper);
7050 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7051 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
7052 WithPressure(0.5f))));
7053
7054 processUp(mapper);
7055 processSync(mapper);
7056 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00007057 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(STYLUS_FUSION_SOURCE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007058 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007059
7060 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7061 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7062}
7063
7064TEST_F(ExternalStylusFusionTest, FusedPointerReportsToolTypeChanges) {
7065 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00007066 auto source = WithSource(STYLUS_FUSION_SOURCE);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007067
7068 mStylusState.pressure = 1.f;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007069 mStylusState.toolType = ToolType::ERASER;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007070 processExternalStylusState(mapper);
7071 processDown(mapper, 100, 200);
7072 processSync(mapper);
7073 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7074 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007075 WithToolType(ToolType::ERASER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007076 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7077
7078 // The external stylus reports a tool change. We wait for some time for a touch event.
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007079 mStylusState.toolType = ToolType::STYLUS;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007080 processExternalStylusState(mapper);
7081 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7082 ASSERT_NO_FATAL_FAILURE(
7083 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7084
7085 // If a touch is reported within the timeout, it reports the updated pressure.
7086 processMove(mapper, 101, 201);
7087 processSync(mapper);
7088 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7089 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007090 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007091 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7092
7093 // There is another tool type change.
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007094 mStylusState.toolType = ToolType::FINGER;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007095 processExternalStylusState(mapper);
7096 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7097 ASSERT_NO_FATAL_FAILURE(
7098 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7099
7100 // If a touch is not reported within the timeout, a move event is generated to report
7101 // the new tool type.
7102 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
7103 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7104 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007105 WithToolType(ToolType::FINGER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007106
7107 processUp(mapper);
7108 processSync(mapper);
7109 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7110 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007111 WithToolType(ToolType::FINGER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007112
7113 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7114 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7115}
7116
7117TEST_F(ExternalStylusFusionTest, FusedPointerReportsButtons) {
7118 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00007119 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007120
7121 ASSERT_NO_FATAL_FAILURE(testStartFusedStylusGesture(mapper));
7122
7123 // The external stylus reports a button change. We wait for some time for a touch event.
7124 mStylusState.buttons = AMOTION_EVENT_BUTTON_STYLUS_PRIMARY;
7125 processExternalStylusState(mapper);
7126 ASSERT_NO_FATAL_FAILURE(
7127 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7128
7129 // If a touch is reported within the timeout, it reports the updated button state.
7130 processMove(mapper, 101, 201);
7131 processSync(mapper);
7132 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7133 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
7134 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
7135 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7136 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
7137 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
7138 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7139
7140 // The button is now released.
7141 mStylusState.buttons = 0;
7142 processExternalStylusState(mapper);
7143 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7144 ASSERT_NO_FATAL_FAILURE(
7145 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7146
7147 // If a touch is not reported within the timeout, a move event is generated to report
7148 // the new button state.
7149 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007150 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7151 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
7152 WithButtonState(0))));
7153 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhan124ea442022-10-28 20:27:44 +00007154 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
7155 WithButtonState(0))));
7156
7157 processUp(mapper);
7158 processSync(mapper);
7159 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007160 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
7161
7162 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7163 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7164}
7165
Michael Wrightd02c5b62014-02-10 15:10:22 -08007166// --- MultiTouchInputMapperTest ---
7167
7168class MultiTouchInputMapperTest : public TouchInputMapperTest {
7169protected:
7170 void prepareAxes(int axes);
7171
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007172 void processPosition(MultiTouchInputMapper& mapper, int32_t x, int32_t y);
7173 void processTouchMajor(MultiTouchInputMapper& mapper, int32_t touchMajor);
7174 void processTouchMinor(MultiTouchInputMapper& mapper, int32_t touchMinor);
7175 void processToolMajor(MultiTouchInputMapper& mapper, int32_t toolMajor);
7176 void processToolMinor(MultiTouchInputMapper& mapper, int32_t toolMinor);
7177 void processOrientation(MultiTouchInputMapper& mapper, int32_t orientation);
7178 void processPressure(MultiTouchInputMapper& mapper, int32_t pressure);
7179 void processDistance(MultiTouchInputMapper& mapper, int32_t distance);
7180 void processId(MultiTouchInputMapper& mapper, int32_t id);
7181 void processSlot(MultiTouchInputMapper& mapper, int32_t slot);
7182 void processToolType(MultiTouchInputMapper& mapper, int32_t toolType);
7183 void processKey(MultiTouchInputMapper& mapper, int32_t code, int32_t value);
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00007184 void processHidUsage(MultiTouchInputMapper& mapper, int32_t usageCode, int32_t value);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007185 void processMTSync(MultiTouchInputMapper& mapper);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00007186 void processSync(MultiTouchInputMapper& mapper, nsecs_t eventTime = ARBITRARY_TIME,
7187 nsecs_t readTime = READ_TIME);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007188};
7189
7190void MultiTouchInputMapperTest::prepareAxes(int axes) {
7191 if (axes & POSITION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007192 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
7193 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007194 }
7195 if (axes & TOUCH) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007196 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN,
7197 RAW_TOUCH_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007198 if (axes & MINOR) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007199 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN,
7200 RAW_TOUCH_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007201 }
7202 }
7203 if (axes & TOOL) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007204 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7205 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007206 if (axes & MINOR) {
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007207 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MIN,
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007208 RAW_TOOL_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007209 }
7210 }
7211 if (axes & ORIENTATION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007212 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_ORIENTATION, RAW_ORIENTATION_MIN,
7213 RAW_ORIENTATION_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007214 }
7215 if (axes & PRESSURE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007216 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_PRESSURE, RAW_PRESSURE_MIN,
7217 RAW_PRESSURE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007218 }
7219 if (axes & DISTANCE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007220 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_DISTANCE, RAW_DISTANCE_MIN,
7221 RAW_DISTANCE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007222 }
7223 if (axes & ID) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007224 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TRACKING_ID, RAW_ID_MIN, RAW_ID_MAX, 0,
7225 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007226 }
7227 if (axes & SLOT) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007228 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_SLOT, RAW_SLOT_MIN, RAW_SLOT_MAX, 0, 0);
7229 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007230 }
7231 if (axes & TOOL_TYPE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007232 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007233 }
7234}
7235
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007236void MultiTouchInputMapperTest::processPosition(MultiTouchInputMapper& mapper, int32_t x,
7237 int32_t y) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007238 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
7239 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007240}
7241
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007242void MultiTouchInputMapperTest::processTouchMajor(MultiTouchInputMapper& mapper,
7243 int32_t touchMajor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007244 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOUCH_MAJOR, touchMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007245}
7246
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007247void MultiTouchInputMapperTest::processTouchMinor(MultiTouchInputMapper& mapper,
7248 int32_t touchMinor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007249 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOUCH_MINOR, touchMinor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007250}
7251
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007252void MultiTouchInputMapperTest::processToolMajor(MultiTouchInputMapper& mapper, int32_t toolMajor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007253 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_WIDTH_MAJOR, toolMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007254}
7255
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007256void MultiTouchInputMapperTest::processToolMinor(MultiTouchInputMapper& mapper, int32_t toolMinor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007257 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_WIDTH_MINOR, toolMinor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007258}
7259
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007260void MultiTouchInputMapperTest::processOrientation(MultiTouchInputMapper& mapper,
7261 int32_t orientation) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007262 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_ORIENTATION, orientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007263}
7264
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007265void MultiTouchInputMapperTest::processPressure(MultiTouchInputMapper& mapper, int32_t pressure) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007266 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_PRESSURE, pressure);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007267}
7268
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007269void MultiTouchInputMapperTest::processDistance(MultiTouchInputMapper& mapper, int32_t distance) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007270 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_DISTANCE, distance);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007271}
7272
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007273void MultiTouchInputMapperTest::processId(MultiTouchInputMapper& mapper, int32_t id) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007274 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TRACKING_ID, id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007275}
7276
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007277void MultiTouchInputMapperTest::processSlot(MultiTouchInputMapper& mapper, int32_t slot) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007278 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_SLOT, slot);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007279}
7280
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007281void MultiTouchInputMapperTest::processToolType(MultiTouchInputMapper& mapper, int32_t toolType) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007282 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOOL_TYPE, toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007283}
7284
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007285void MultiTouchInputMapperTest::processKey(MultiTouchInputMapper& mapper, int32_t code,
7286 int32_t value) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007287 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007288}
7289
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00007290void MultiTouchInputMapperTest::processHidUsage(MultiTouchInputMapper& mapper, int32_t usageCode,
7291 int32_t value) {
7292 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, usageCode);
7293 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, value);
7294}
7295
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007296void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper& mapper) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007297 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_MT_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007298}
7299
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00007300void MultiTouchInputMapperTest::processSync(MultiTouchInputMapper& mapper, nsecs_t eventTime,
7301 nsecs_t readTime) {
7302 process(mapper, eventTime, readTime, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007303}
7304
Michael Wrightd02c5b62014-02-10 15:10:22 -08007305TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackingIds) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007306 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007307 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007308 prepareAxes(POSITION);
7309 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007310 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007311
arthurhungdcef2dc2020-08-11 14:47:50 +08007312 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007313
7314 NotifyMotionArgs motionArgs;
7315
7316 // Two fingers down at once.
7317 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7318 processPosition(mapper, x1, y1);
7319 processMTSync(mapper);
7320 processPosition(mapper, x2, y2);
7321 processMTSync(mapper);
7322 processSync(mapper);
7323
7324 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7325 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7326 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7327 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7328 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7329 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
7330 ASSERT_EQ(0, motionArgs.flags);
7331 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7332 ASSERT_EQ(0, motionArgs.buttonState);
7333 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007334 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007335 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007336 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].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_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7340 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7341 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7342
7343 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7344 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7345 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7346 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7347 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007348 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007349 ASSERT_EQ(0, motionArgs.flags);
7350 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7351 ASSERT_EQ(0, motionArgs.buttonState);
7352 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007353 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007354 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007355 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007356 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007357 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007358 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7359 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7360 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7361 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7362 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7363 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7364 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7365
7366 // Move.
7367 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7368 processPosition(mapper, x1, y1);
7369 processMTSync(mapper);
7370 processPosition(mapper, x2, y2);
7371 processMTSync(mapper);
7372 processSync(mapper);
7373
7374 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7375 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7376 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7377 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7378 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7379 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7380 ASSERT_EQ(0, motionArgs.flags);
7381 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7382 ASSERT_EQ(0, motionArgs.buttonState);
7383 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007384 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007385 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007386 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007387 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007388 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007389 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7390 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7391 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7392 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7393 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7394 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7395 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7396
7397 // First finger up.
7398 x2 += 15; y2 -= 20;
7399 processPosition(mapper, x2, y2);
7400 processMTSync(mapper);
7401 processSync(mapper);
7402
7403 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7404 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7405 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7406 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7407 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007408 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007409 ASSERT_EQ(0, motionArgs.flags);
7410 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7411 ASSERT_EQ(0, motionArgs.buttonState);
7412 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007413 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007414 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007415 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007416 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007417 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007418 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7419 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7420 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7421 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7422 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7423 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7424 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
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);
7431 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7432 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(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007437 ASSERT_EQ(1, 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_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7440 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7441 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7442 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7443 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7444
7445 // Move.
7446 x2 += 20; y2 -= 25;
7447 processPosition(mapper, x2, y2);
7448 processMTSync(mapper);
7449 processSync(mapper);
7450
7451 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7452 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7453 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7454 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7455 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7456 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7457 ASSERT_EQ(0, motionArgs.flags);
7458 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7459 ASSERT_EQ(0, motionArgs.buttonState);
7460 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007461 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007462 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007463 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007464 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7465 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7466 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7467 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7468 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7469
7470 // New finger down.
7471 int32_t x3 = 700, y3 = 300;
7472 processPosition(mapper, x2, y2);
7473 processMTSync(mapper);
7474 processPosition(mapper, x3, y3);
7475 processMTSync(mapper);
7476 processSync(mapper);
7477
7478 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7479 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7480 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7481 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7482 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007483 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007484 ASSERT_EQ(0, motionArgs.flags);
7485 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7486 ASSERT_EQ(0, motionArgs.buttonState);
7487 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007488 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007489 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007490 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007491 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007492 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007493 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7494 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7495 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7496 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7497 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7498 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7499 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7500
7501 // Second finger up.
7502 x3 += 30; y3 -= 20;
7503 processPosition(mapper, x3, y3);
7504 processMTSync(mapper);
7505 processSync(mapper);
7506
7507 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7508 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7509 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7510 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7511 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007512 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007513 ASSERT_EQ(0, motionArgs.flags);
7514 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7515 ASSERT_EQ(0, motionArgs.buttonState);
7516 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007517 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007518 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007519 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007520 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007521 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007522 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7523 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7524 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7525 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7526 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7527 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7528 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7529
7530 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7531 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7532 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7533 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7534 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7535 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7536 ASSERT_EQ(0, motionArgs.flags);
7537 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7538 ASSERT_EQ(0, motionArgs.buttonState);
7539 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007540 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007541 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007542 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007543 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7544 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7545 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7546 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7547 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7548
7549 // Last finger up.
7550 processMTSync(mapper);
7551 processSync(mapper);
7552
7553 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7554 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7555 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7556 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7557 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7558 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
7559 ASSERT_EQ(0, motionArgs.flags);
7560 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7561 ASSERT_EQ(0, motionArgs.buttonState);
7562 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007563 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007564 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007565 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007566 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7567 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7568 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7569 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7570 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7571
7572 // Should not have sent any more keys or motions.
7573 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7574 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7575}
7576
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007577TEST_F(MultiTouchInputMapperTest, AxisResolution_IsPopulated) {
7578 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007579 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007580
7581 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, /*flat*/ 0,
7582 /*fuzz*/ 0, /*resolution*/ 10);
7583 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, /*flat*/ 0,
7584 /*fuzz*/ 0, /*resolution*/ 11);
7585 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX,
7586 /*flat*/ 0, /*fuzz*/ 0, /*resolution*/ 12);
7587 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX,
7588 /*flat*/ 0, /*fuzz*/ 0, /*resolution*/ 13);
7589 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7590 /*flat*/ 0, /*flat*/ 0, /*resolution*/ 14);
7591 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7592 /*flat*/ 0, /*flat*/ 0, /*resolution*/ 15);
7593
Arpit Singha8c236b2023-04-25 13:56:05 +00007594 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007595
7596 // X and Y axes
7597 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_X, 10 / X_PRECISION);
7598 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_Y, 11 / Y_PRECISION);
7599 // Touch major and minor
7600 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOUCH_MAJOR, 12 * GEOMETRIC_SCALE);
7601 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOUCH_MINOR, 13 * GEOMETRIC_SCALE);
7602 // Tool major and minor
7603 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOOL_MAJOR, 14 * GEOMETRIC_SCALE);
7604 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOOL_MINOR, 15 * GEOMETRIC_SCALE);
7605}
7606
7607TEST_F(MultiTouchInputMapperTest, TouchMajorAndMinorAxes_DoNotAppearIfNotSupported) {
7608 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007609 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007610
7611 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, /*flat*/ 0,
7612 /*fuzz*/ 0, /*resolution*/ 10);
7613 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, /*flat*/ 0,
7614 /*fuzz*/ 0, /*resolution*/ 11);
7615
7616 // We do not add ABS_MT_TOUCH_MAJOR / MINOR or ABS_MT_WIDTH_MAJOR / MINOR axes
7617
Arpit Singha8c236b2023-04-25 13:56:05 +00007618 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007619
7620 // Touch major and minor
7621 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOUCH_MAJOR);
7622 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOUCH_MINOR);
7623 // Tool major and minor
7624 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOOL_MAJOR);
7625 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOOL_MINOR);
7626}
7627
Michael Wrightd02c5b62014-02-10 15:10:22 -08007628TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingIds) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007629 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007630 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007631 prepareAxes(POSITION | ID);
7632 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007633 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007634
arthurhungdcef2dc2020-08-11 14:47:50 +08007635 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007636
7637 NotifyMotionArgs motionArgs;
7638
7639 // Two fingers down at once.
7640 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7641 processPosition(mapper, x1, y1);
7642 processId(mapper, 1);
7643 processMTSync(mapper);
7644 processPosition(mapper, x2, y2);
7645 processId(mapper, 2);
7646 processMTSync(mapper);
7647 processSync(mapper);
7648
7649 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7650 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007651 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007652 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007653 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007654 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7655 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7656
7657 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007658 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007659 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007660 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007661 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007662 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007663 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007664 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7665 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7666 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7667 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7668
7669 // Move.
7670 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7671 processPosition(mapper, x1, y1);
7672 processId(mapper, 1);
7673 processMTSync(mapper);
7674 processPosition(mapper, x2, y2);
7675 processId(mapper, 2);
7676 processMTSync(mapper);
7677 processSync(mapper);
7678
7679 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7680 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007681 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007682 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007683 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007684 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007685 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007686 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7687 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7688 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7689 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7690
7691 // First finger up.
7692 x2 += 15; y2 -= 20;
7693 processPosition(mapper, x2, y2);
7694 processId(mapper, 2);
7695 processMTSync(mapper);
7696 processSync(mapper);
7697
7698 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007699 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007700 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007701 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007702 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007703 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007704 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007705 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7706 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7707 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7708 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7709
7710 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7711 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007712 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007713 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007714 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007715 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7716 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7717
7718 // Move.
7719 x2 += 20; y2 -= 25;
7720 processPosition(mapper, x2, y2);
7721 processId(mapper, 2);
7722 processMTSync(mapper);
7723 processSync(mapper);
7724
7725 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7726 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007727 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007728 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007729 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007730 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7731 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7732
7733 // New finger down.
7734 int32_t x3 = 700, y3 = 300;
7735 processPosition(mapper, x2, y2);
7736 processId(mapper, 2);
7737 processMTSync(mapper);
7738 processPosition(mapper, x3, y3);
7739 processId(mapper, 3);
7740 processMTSync(mapper);
7741 processSync(mapper);
7742
7743 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007744 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007745 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007746 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007747 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007748 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007749 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007750 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7751 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7752 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7753 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7754
7755 // Second finger up.
7756 x3 += 30; y3 -= 20;
7757 processPosition(mapper, x3, y3);
7758 processId(mapper, 3);
7759 processMTSync(mapper);
7760 processSync(mapper);
7761
7762 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007763 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007764 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007765 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007766 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007767 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007768 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007769 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7770 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7771 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7772 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7773
7774 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7775 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007776 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007777 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007778 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007779 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7780 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7781
7782 // Last finger up.
7783 processMTSync(mapper);
7784 processSync(mapper);
7785
7786 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7787 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007788 ASSERT_EQ(size_t(1), 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_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7792 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7793
7794 // Should not have sent any more keys or motions.
7795 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7796 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7797}
7798
7799TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithSlots) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007800 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007801 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007802 prepareAxes(POSITION | ID | SLOT);
7803 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007804 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007805
arthurhungdcef2dc2020-08-11 14:47:50 +08007806 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007807
7808 NotifyMotionArgs motionArgs;
7809
7810 // Two fingers down at once.
7811 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7812 processPosition(mapper, x1, y1);
7813 processId(mapper, 1);
7814 processSlot(mapper, 1);
7815 processPosition(mapper, x2, y2);
7816 processId(mapper, 2);
7817 processSync(mapper);
7818
7819 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7820 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007821 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007822 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007823 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007824 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7825 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7826
7827 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007828 ASSERT_EQ(ACTION_POINTER_1_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(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7836 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7837 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7838
7839 // Move.
7840 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7841 processSlot(mapper, 0);
7842 processPosition(mapper, x1, y1);
7843 processSlot(mapper, 1);
7844 processPosition(mapper, x2, y2);
7845 processSync(mapper);
7846
7847 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7848 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, 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(x1), toDisplayY(y1), 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 // First finger up.
7860 x2 += 15; y2 -= 20;
7861 processSlot(mapper, 0);
7862 processId(mapper, -1);
7863 processSlot(mapper, 1);
7864 processPosition(mapper, x2, y2);
7865 processSync(mapper);
7866
7867 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007868 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007869 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007870 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007871 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007872 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007873 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007874 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7875 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7876 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7877 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7878
7879 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7880 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007881 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007882 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007883 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007884 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7885 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7886
7887 // Move.
7888 x2 += 20; y2 -= 25;
7889 processPosition(mapper, x2, y2);
7890 processSync(mapper);
7891
7892 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7893 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007894 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007895 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007896 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007897 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7898 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7899
7900 // New finger down.
7901 int32_t x3 = 700, y3 = 300;
7902 processPosition(mapper, x2, y2);
7903 processSlot(mapper, 0);
7904 processId(mapper, 3);
7905 processPosition(mapper, x3, y3);
7906 processSync(mapper);
7907
7908 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007909 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007910 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007911 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007912 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007913 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007914 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007915 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7916 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7917 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7918 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7919
7920 // Second finger up.
7921 x3 += 30; y3 -= 20;
7922 processSlot(mapper, 1);
7923 processId(mapper, -1);
7924 processSlot(mapper, 0);
7925 processPosition(mapper, x3, y3);
7926 processSync(mapper);
7927
7928 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007929 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007930 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007931 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007932 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007933 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007934 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007935 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7936 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7937 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7938 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7939
7940 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7941 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007942 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007943 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007944 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007945 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7946 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7947
7948 // Last finger up.
7949 processId(mapper, -1);
7950 processSync(mapper);
7951
7952 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7953 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007954 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007955 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007956 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007957 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7958 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7959
7960 // Should not have sent any more keys or motions.
7961 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7962 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7963}
7964
7965TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007966 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007967 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007968 prepareAxes(POSITION | TOUCH | TOOL | PRESSURE | ORIENTATION | ID | MINOR | DISTANCE);
Arpit Singha8c236b2023-04-25 13:56:05 +00007969 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007970
7971 // These calculations are based on the input device calibration documentation.
7972 int32_t rawX = 100;
7973 int32_t rawY = 200;
7974 int32_t rawTouchMajor = 7;
7975 int32_t rawTouchMinor = 6;
7976 int32_t rawToolMajor = 9;
7977 int32_t rawToolMinor = 8;
7978 int32_t rawPressure = 11;
7979 int32_t rawDistance = 0;
7980 int32_t rawOrientation = 3;
7981 int32_t id = 5;
7982
7983 float x = toDisplayX(rawX);
7984 float y = toDisplayY(rawY);
7985 float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
7986 float size = avg(rawTouchMajor, rawTouchMinor) / RAW_TOUCH_MAX;
7987 float toolMajor = float(rawToolMajor) * GEOMETRIC_SCALE;
7988 float toolMinor = float(rawToolMinor) * GEOMETRIC_SCALE;
7989 float touchMajor = float(rawTouchMajor) * GEOMETRIC_SCALE;
7990 float touchMinor = float(rawTouchMinor) * GEOMETRIC_SCALE;
7991 float orientation = float(rawOrientation) / RAW_ORIENTATION_MAX * M_PI_2;
7992 float distance = float(rawDistance);
7993
7994 processPosition(mapper, rawX, rawY);
7995 processTouchMajor(mapper, rawTouchMajor);
7996 processTouchMinor(mapper, rawTouchMinor);
7997 processToolMajor(mapper, rawToolMajor);
7998 processToolMinor(mapper, rawToolMinor);
7999 processPressure(mapper, rawPressure);
8000 processOrientation(mapper, rawOrientation);
8001 processDistance(mapper, rawDistance);
8002 processId(mapper, id);
8003 processMTSync(mapper);
8004 processSync(mapper);
8005
8006 NotifyMotionArgs args;
8007 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8008 ASSERT_EQ(0, args.pointerProperties[0].id);
8009 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8010 x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor,
8011 orientation, distance));
Prabir Pradhan9a53b552024-06-04 02:59:40 +00008012 ASSERT_EQ(args.flags, AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008013}
8014
8015TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_GeometricCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008016 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008017 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008018 prepareAxes(POSITION | TOUCH | TOOL | MINOR);
8019 addConfigurationProperty("touch.size.calibration", "geometric");
Arpit Singha8c236b2023-04-25 13:56:05 +00008020 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008021
8022 // These calculations are based on the input device calibration documentation.
8023 int32_t rawX = 100;
8024 int32_t rawY = 200;
8025 int32_t rawTouchMajor = 140;
8026 int32_t rawTouchMinor = 120;
8027 int32_t rawToolMajor = 180;
8028 int32_t rawToolMinor = 160;
8029
8030 float x = toDisplayX(rawX);
8031 float y = toDisplayY(rawY);
8032 float size = avg(rawTouchMajor, rawTouchMinor) / RAW_TOUCH_MAX;
8033 float toolMajor = float(rawToolMajor) * GEOMETRIC_SCALE;
8034 float toolMinor = float(rawToolMinor) * GEOMETRIC_SCALE;
8035 float touchMajor = float(rawTouchMajor) * GEOMETRIC_SCALE;
8036 float touchMinor = float(rawTouchMinor) * GEOMETRIC_SCALE;
8037
8038 processPosition(mapper, rawX, rawY);
8039 processTouchMajor(mapper, rawTouchMajor);
8040 processTouchMinor(mapper, rawTouchMinor);
8041 processToolMajor(mapper, rawToolMajor);
8042 processToolMinor(mapper, rawToolMinor);
8043 processMTSync(mapper);
8044 processSync(mapper);
8045
8046 NotifyMotionArgs args;
8047 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8048 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8049 x, y, 1.0f, size, touchMajor, touchMinor, toolMajor, toolMinor, 0, 0));
8050}
8051
8052TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_SummedLinearCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008053 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008054 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008055 prepareAxes(POSITION | TOUCH | TOOL);
8056 addConfigurationProperty("touch.size.calibration", "diameter");
8057 addConfigurationProperty("touch.size.scale", "10");
8058 addConfigurationProperty("touch.size.bias", "160");
8059 addConfigurationProperty("touch.size.isSummed", "1");
Arpit Singha8c236b2023-04-25 13:56:05 +00008060 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008061
8062 // These calculations are based on the input device calibration documentation.
8063 // Note: We only provide a single common touch/tool value because the device is assumed
8064 // not to emit separate values for each pointer (isSummed = 1).
8065 int32_t rawX = 100;
8066 int32_t rawY = 200;
8067 int32_t rawX2 = 150;
8068 int32_t rawY2 = 250;
8069 int32_t rawTouchMajor = 5;
8070 int32_t rawToolMajor = 8;
8071
8072 float x = toDisplayX(rawX);
8073 float y = toDisplayY(rawY);
8074 float x2 = toDisplayX(rawX2);
8075 float y2 = toDisplayY(rawY2);
8076 float size = float(rawTouchMajor) / 2 / RAW_TOUCH_MAX;
8077 float touch = float(rawTouchMajor) / 2 * 10.0f + 160.0f;
8078 float tool = float(rawToolMajor) / 2 * 10.0f + 160.0f;
8079
8080 processPosition(mapper, rawX, rawY);
8081 processTouchMajor(mapper, rawTouchMajor);
8082 processToolMajor(mapper, rawToolMajor);
8083 processMTSync(mapper);
8084 processPosition(mapper, rawX2, rawY2);
8085 processTouchMajor(mapper, rawTouchMajor);
8086 processToolMajor(mapper, rawToolMajor);
8087 processMTSync(mapper);
8088 processSync(mapper);
8089
8090 NotifyMotionArgs args;
8091 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8092 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
8093
8094 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08008095 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07008096 ASSERT_EQ(size_t(2), args.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08008097 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8098 x, y, 1.0f, size, touch, touch, tool, tool, 0, 0));
8099 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[1],
8100 x2, y2, 1.0f, size, touch, touch, tool, tool, 0, 0));
8101}
8102
8103TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_AreaCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008104 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008105 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008106 prepareAxes(POSITION | TOUCH | TOOL);
8107 addConfigurationProperty("touch.size.calibration", "area");
8108 addConfigurationProperty("touch.size.scale", "43");
8109 addConfigurationProperty("touch.size.bias", "3");
Arpit Singha8c236b2023-04-25 13:56:05 +00008110 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008111
8112 // These calculations are based on the input device calibration documentation.
8113 int32_t rawX = 100;
8114 int32_t rawY = 200;
8115 int32_t rawTouchMajor = 5;
8116 int32_t rawToolMajor = 8;
8117
8118 float x = toDisplayX(rawX);
8119 float y = toDisplayY(rawY);
8120 float size = float(rawTouchMajor) / RAW_TOUCH_MAX;
8121 float touch = sqrtf(rawTouchMajor) * 43.0f + 3.0f;
8122 float tool = sqrtf(rawToolMajor) * 43.0f + 3.0f;
8123
8124 processPosition(mapper, rawX, rawY);
8125 processTouchMajor(mapper, rawTouchMajor);
8126 processToolMajor(mapper, rawToolMajor);
8127 processMTSync(mapper);
8128 processSync(mapper);
8129
8130 NotifyMotionArgs args;
8131 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8132 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8133 x, y, 1.0f, size, touch, touch, tool, tool, 0, 0));
8134}
8135
8136TEST_F(MultiTouchInputMapperTest, Process_PressureAxis_AmplitudeCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008137 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008138 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008139 prepareAxes(POSITION | PRESSURE);
8140 addConfigurationProperty("touch.pressure.calibration", "amplitude");
8141 addConfigurationProperty("touch.pressure.scale", "0.01");
Arpit Singha8c236b2023-04-25 13:56:05 +00008142 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008143
Michael Wrightaa449c92017-12-13 21:21:43 +00008144 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +00008145 mapper.populateDeviceInfo(info);
Michael Wrightaa449c92017-12-13 21:21:43 +00008146 ASSERT_NO_FATAL_FAILURE(assertMotionRange(info,
8147 AINPUT_MOTION_RANGE_PRESSURE, AINPUT_SOURCE_TOUCHSCREEN,
8148 0.0f, RAW_PRESSURE_MAX * 0.01, 0.0f, 0.0f));
8149
Michael Wrightd02c5b62014-02-10 15:10:22 -08008150 // These calculations are based on the input device calibration documentation.
8151 int32_t rawX = 100;
8152 int32_t rawY = 200;
8153 int32_t rawPressure = 60;
8154
8155 float x = toDisplayX(rawX);
8156 float y = toDisplayY(rawY);
8157 float pressure = float(rawPressure) * 0.01f;
8158
8159 processPosition(mapper, rawX, rawY);
8160 processPressure(mapper, rawPressure);
8161 processMTSync(mapper);
8162 processSync(mapper);
8163
8164 NotifyMotionArgs args;
8165 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8166 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8167 x, y, pressure, 0, 0, 0, 0, 0, 0, 0));
8168}
8169
8170TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllButtons) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008171 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008172 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008173 prepareAxes(POSITION | ID | SLOT);
Arpit Singha8c236b2023-04-25 13:56:05 +00008174 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008175
8176 NotifyMotionArgs motionArgs;
8177 NotifyKeyArgs keyArgs;
8178
8179 processId(mapper, 1);
8180 processPosition(mapper, 100, 200);
8181 processSync(mapper);
8182 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8183 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8184 ASSERT_EQ(0, motionArgs.buttonState);
8185
8186 // press BTN_LEFT, release BTN_LEFT
8187 processKey(mapper, BTN_LEFT, 1);
8188 processSync(mapper);
8189 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8190 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
8191 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
8192
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008193 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8194 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8195 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
8196
Michael Wrightd02c5b62014-02-10 15:10:22 -08008197 processKey(mapper, BTN_LEFT, 0);
8198 processSync(mapper);
8199 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008200 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008201 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008202
8203 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008204 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008205 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008206
8207 // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
8208 processKey(mapper, BTN_RIGHT, 1);
8209 processKey(mapper, BTN_MIDDLE, 1);
8210 processSync(mapper);
8211 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8212 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
8213 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
8214 motionArgs.buttonState);
8215
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008216 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8217 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8218 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
8219
8220 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8221 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8222 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
8223 motionArgs.buttonState);
8224
Michael Wrightd02c5b62014-02-10 15:10:22 -08008225 processKey(mapper, BTN_RIGHT, 0);
8226 processSync(mapper);
8227 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008228 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008229 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008230
8231 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008232 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008233 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008234
8235 processKey(mapper, BTN_MIDDLE, 0);
8236 processSync(mapper);
8237 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008238 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008239 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008240
8241 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008242 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008243 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008244
8245 // press BTN_BACK, release BTN_BACK
8246 processKey(mapper, BTN_BACK, 1);
8247 processSync(mapper);
8248 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8249 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8250 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008251
Michael Wrightd02c5b62014-02-10 15:10:22 -08008252 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008253 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008254 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
8255
8256 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8257 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8258 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008259
8260 processKey(mapper, BTN_BACK, 0);
8261 processSync(mapper);
8262 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008263 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008264 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008265
8266 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008267 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008268 ASSERT_EQ(0, motionArgs.buttonState);
8269
Michael Wrightd02c5b62014-02-10 15:10:22 -08008270 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8271 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8272 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
8273
8274 // press BTN_SIDE, release BTN_SIDE
8275 processKey(mapper, BTN_SIDE, 1);
8276 processSync(mapper);
8277 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8278 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8279 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008280
Michael Wrightd02c5b62014-02-10 15:10:22 -08008281 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008282 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008283 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
8284
8285 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8286 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8287 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008288
8289 processKey(mapper, BTN_SIDE, 0);
8290 processSync(mapper);
8291 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008292 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008293 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008294
8295 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008296 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008297 ASSERT_EQ(0, motionArgs.buttonState);
8298
Michael Wrightd02c5b62014-02-10 15:10:22 -08008299 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8300 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8301 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
8302
8303 // press BTN_FORWARD, release BTN_FORWARD
8304 processKey(mapper, BTN_FORWARD, 1);
8305 processSync(mapper);
8306 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8307 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8308 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008309
Michael Wrightd02c5b62014-02-10 15:10:22 -08008310 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008311 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008312 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
8313
8314 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8315 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8316 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008317
8318 processKey(mapper, BTN_FORWARD, 0);
8319 processSync(mapper);
8320 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008321 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008322 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008323
8324 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008325 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008326 ASSERT_EQ(0, motionArgs.buttonState);
8327
Michael Wrightd02c5b62014-02-10 15:10:22 -08008328 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8329 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8330 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
8331
8332 // press BTN_EXTRA, release BTN_EXTRA
8333 processKey(mapper, BTN_EXTRA, 1);
8334 processSync(mapper);
8335 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8336 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8337 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008338
Michael Wrightd02c5b62014-02-10 15:10:22 -08008339 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008340 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008341 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
8342
8343 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8344 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8345 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008346
8347 processKey(mapper, BTN_EXTRA, 0);
8348 processSync(mapper);
8349 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008350 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008351 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008352
8353 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008354 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008355 ASSERT_EQ(0, motionArgs.buttonState);
8356
Michael Wrightd02c5b62014-02-10 15:10:22 -08008357 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8358 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8359 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
8360
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008361 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
8362
Michael Wrightd02c5b62014-02-10 15:10:22 -08008363 // press BTN_STYLUS, release BTN_STYLUS
8364 processKey(mapper, BTN_STYLUS, 1);
8365 processSync(mapper);
8366 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8367 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008368 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
8369
8370 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8371 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8372 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008373
8374 processKey(mapper, BTN_STYLUS, 0);
8375 processSync(mapper);
8376 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008377 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008378 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008379
8380 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008381 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008382 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008383
8384 // press BTN_STYLUS2, release BTN_STYLUS2
8385 processKey(mapper, BTN_STYLUS2, 1);
8386 processSync(mapper);
8387 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8388 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008389 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
8390
8391 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8392 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8393 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008394
8395 processKey(mapper, BTN_STYLUS2, 0);
8396 processSync(mapper);
8397 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008398 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008399 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008400
8401 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008402 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008403 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008404
8405 // release touch
8406 processId(mapper, -1);
8407 processSync(mapper);
8408 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8409 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8410 ASSERT_EQ(0, motionArgs.buttonState);
8411}
8412
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008413TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleMappedStylusButtons) {
8414 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008415 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008416 prepareAxes(POSITION | ID | SLOT);
Arpit Singha8c236b2023-04-25 13:56:05 +00008417 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008418
8419 mFakeEventHub->addKey(EVENTHUB_ID, BTN_A, 0, AKEYCODE_STYLUS_BUTTON_PRIMARY, 0);
8420 mFakeEventHub->addKey(EVENTHUB_ID, 0, 0xabcd, AKEYCODE_STYLUS_BUTTON_SECONDARY, 0);
8421
8422 // Touch down.
8423 processId(mapper, 1);
8424 processPosition(mapper, 100, 200);
8425 processSync(mapper);
8426 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8427 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithButtonState(0))));
8428
8429 // Press and release button mapped to the primary stylus button.
8430 processKey(mapper, BTN_A, 1);
8431 processSync(mapper);
8432 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8433 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
8434 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
8435 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8436 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
8437 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
8438
8439 processKey(mapper, BTN_A, 0);
8440 processSync(mapper);
8441 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8442 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithButtonState(0))));
8443 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8444 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
8445
8446 // Press and release the HID usage mapped to the secondary stylus button.
8447 processHidUsage(mapper, 0xabcd, 1);
8448 processSync(mapper);
8449 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8450 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
8451 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY))));
8452 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8453 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
8454 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY))));
8455
8456 processHidUsage(mapper, 0xabcd, 0);
8457 processSync(mapper);
8458 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8459 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithButtonState(0))));
8460 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8461 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
8462
8463 // Release touch.
8464 processId(mapper, -1);
8465 processSync(mapper);
8466 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8467 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
8468}
8469
Michael Wrightd02c5b62014-02-10 15:10:22 -08008470TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008471 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008472 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008473 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00008474 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008475
8476 NotifyMotionArgs motionArgs;
8477
8478 // default tool type is finger
8479 processId(mapper, 1);
8480 processPosition(mapper, 100, 200);
8481 processSync(mapper);
8482 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8483 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008484 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008485
8486 // eraser
8487 processKey(mapper, BTN_TOOL_RUBBER, 1);
8488 processSync(mapper);
8489 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8490 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008491 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008492
8493 // stylus
8494 processKey(mapper, BTN_TOOL_RUBBER, 0);
8495 processKey(mapper, BTN_TOOL_PEN, 1);
8496 processSync(mapper);
8497 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8498 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008499 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008500
8501 // brush
8502 processKey(mapper, BTN_TOOL_PEN, 0);
8503 processKey(mapper, BTN_TOOL_BRUSH, 1);
8504 processSync(mapper);
8505 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8506 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008507 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008508
8509 // pencil
8510 processKey(mapper, BTN_TOOL_BRUSH, 0);
8511 processKey(mapper, BTN_TOOL_PENCIL, 1);
8512 processSync(mapper);
8513 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8514 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008515 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008516
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08008517 // air-brush
Michael Wrightd02c5b62014-02-10 15:10:22 -08008518 processKey(mapper, BTN_TOOL_PENCIL, 0);
8519 processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
8520 processSync(mapper);
8521 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8522 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008523 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008524
8525 // mouse
8526 processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
8527 processKey(mapper, BTN_TOOL_MOUSE, 1);
8528 processSync(mapper);
8529 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8530 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008531 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008532
8533 // lens
8534 processKey(mapper, BTN_TOOL_MOUSE, 0);
8535 processKey(mapper, BTN_TOOL_LENS, 1);
8536 processSync(mapper);
8537 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8538 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008539 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008540
8541 // double-tap
8542 processKey(mapper, BTN_TOOL_LENS, 0);
8543 processKey(mapper, BTN_TOOL_DOUBLETAP, 1);
8544 processSync(mapper);
8545 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8546 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008547 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008548
8549 // triple-tap
8550 processKey(mapper, BTN_TOOL_DOUBLETAP, 0);
8551 processKey(mapper, BTN_TOOL_TRIPLETAP, 1);
8552 processSync(mapper);
8553 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8554 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008555 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008556
8557 // quad-tap
8558 processKey(mapper, BTN_TOOL_TRIPLETAP, 0);
8559 processKey(mapper, BTN_TOOL_QUADTAP, 1);
8560 processSync(mapper);
8561 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8562 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008563 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008564
8565 // finger
8566 processKey(mapper, BTN_TOOL_QUADTAP, 0);
8567 processKey(mapper, BTN_TOOL_FINGER, 1);
8568 processSync(mapper);
8569 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8570 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008571 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008572
8573 // stylus trumps finger
8574 processKey(mapper, BTN_TOOL_PEN, 1);
8575 processSync(mapper);
8576 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8577 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008578 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008579
8580 // eraser trumps stylus
8581 processKey(mapper, BTN_TOOL_RUBBER, 1);
8582 processSync(mapper);
8583 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8584 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008585 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008586
8587 // mouse trumps eraser
8588 processKey(mapper, BTN_TOOL_MOUSE, 1);
8589 processSync(mapper);
8590 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8591 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008592 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008593
8594 // MT tool type trumps BTN tool types: MT_TOOL_FINGER
8595 processToolType(mapper, MT_TOOL_FINGER); // this is the first time we send MT_TOOL_TYPE
8596 processSync(mapper);
8597 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8598 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008599 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008600
8601 // MT tool type trumps BTN tool types: MT_TOOL_PEN
8602 processToolType(mapper, MT_TOOL_PEN);
8603 processSync(mapper);
8604 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8605 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008606 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008607
8608 // back to default tool type
8609 processToolType(mapper, -1); // use a deliberately undefined tool type, for testing
8610 processKey(mapper, BTN_TOOL_MOUSE, 0);
8611 processKey(mapper, BTN_TOOL_RUBBER, 0);
8612 processKey(mapper, BTN_TOOL_PEN, 0);
8613 processKey(mapper, BTN_TOOL_FINGER, 0);
8614 processSync(mapper);
8615 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8616 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008617 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008618}
8619
8620TEST_F(MultiTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008621 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008622 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008623 prepareAxes(POSITION | ID | SLOT);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008624 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00008625 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008626
8627 NotifyMotionArgs motionArgs;
8628
8629 // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0
8630 processId(mapper, 1);
8631 processPosition(mapper, 100, 200);
8632 processSync(mapper);
8633 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8634 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8635 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8636 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8637
8638 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8639 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8640 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8641 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8642
8643 // move a little
8644 processPosition(mapper, 150, 250);
8645 processSync(mapper);
8646 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8647 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8648 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8649 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8650
8651 // down when BTN_TOUCH is pressed, pressure defaults to 1
8652 processKey(mapper, BTN_TOUCH, 1);
8653 processSync(mapper);
8654 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8655 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8656 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8657 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8658
8659 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8660 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8661 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8662 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8663
8664 // up when BTN_TOUCH is released, hover restored
8665 processKey(mapper, BTN_TOUCH, 0);
8666 processSync(mapper);
8667 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8668 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8669 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8670 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8671
8672 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8673 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8674 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8675 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8676
8677 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8678 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8679 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8680 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8681
8682 // exit hover when pointer goes away
8683 processId(mapper, -1);
8684 processSync(mapper);
8685 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8686 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8687 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8688 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8689}
8690
8691TEST_F(MultiTouchInputMapperTest, Process_WhenAbsMTPressureIsPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008692 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008693 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008694 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00008695 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008696
8697 NotifyMotionArgs motionArgs;
8698
8699 // initially hovering because pressure is 0
8700 processId(mapper, 1);
8701 processPosition(mapper, 100, 200);
8702 processPressure(mapper, 0);
8703 processSync(mapper);
8704 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8705 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8706 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8707 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8708
8709 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8710 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8711 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8712 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8713
8714 // move a little
8715 processPosition(mapper, 150, 250);
8716 processSync(mapper);
8717 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8718 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8719 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8720 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8721
8722 // down when pressure becomes non-zero
8723 processPressure(mapper, RAW_PRESSURE_MAX);
8724 processSync(mapper);
8725 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8726 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8727 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8728 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8729
8730 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8731 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8732 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8733 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8734
8735 // up when pressure becomes 0, hover restored
8736 processPressure(mapper, 0);
8737 processSync(mapper);
8738 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8739 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8740 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8741 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8742
8743 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8744 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8745 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8746 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8747
8748 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8749 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8750 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8751 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8752
8753 // exit hover when pointer goes away
8754 processId(mapper, -1);
8755 processSync(mapper);
8756 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8757 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8758 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8759 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8760}
8761
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008762/**
8763 * Set the input device port <--> display port associations, and check that the
8764 * events are routed to the display that matches the display port.
8765 * This can be checked by looking at the displayId of the resulting NotifyMotionArgs.
8766 */
8767TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayPort) {
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008768 const std::string usb2 = "USB2";
8769 const uint8_t hdmi1 = 0;
8770 const uint8_t hdmi2 = 1;
8771 const std::string secondaryUniqueId = "uniqueId2";
Michael Wrightfe3de7d2020-07-02 19:05:30 +01008772 constexpr ViewportType type = ViewportType::EXTERNAL;
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008773
8774 addConfigurationProperty("touch.deviceType", "touchScreen");
8775 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008776 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008777
8778 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
8779 mFakePolicy->addInputPortAssociation(usb2, hdmi2);
8780
8781 // We are intentionally not adding the viewport for display 1 yet. Since the port association
8782 // for this input device is specified, and the matching viewport is not present,
8783 // the input device should be disabled (at the mapper level).
8784
8785 // Add viewport for display 2 on hdmi2
8786 prepareSecondaryDisplay(type, hdmi2);
8787 // Send a touch event
8788 processPosition(mapper, 100, 100);
8789 processSync(mapper);
8790 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
8791
8792 // Add viewport for display 1 on hdmi1
Michael Wrighta9cf4192022-12-01 23:46:39 +00008793 prepareDisplay(ui::ROTATION_0, hdmi1);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008794 // Send a touch event again
8795 processPosition(mapper, 100, 100);
8796 processSync(mapper);
8797
8798 NotifyMotionArgs args;
8799 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8800 ASSERT_EQ(DISPLAY_ID, args.displayId);
8801}
Michael Wrightd02c5b62014-02-10 15:10:22 -08008802
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008803TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayUniqueId) {
8804 addConfigurationProperty("touch.deviceType", "touchScreen");
8805 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008806 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008807
8808 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID);
8809
Michael Wrighta9cf4192022-12-01 23:46:39 +00008810 prepareDisplay(ui::ROTATION_0);
8811 prepareVirtualDisplay(ui::ROTATION_0);
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008812
8813 // Send a touch event
8814 processPosition(mapper, 100, 100);
8815 processSync(mapper);
8816
8817 NotifyMotionArgs args;
8818 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8819 ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId);
8820}
8821
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008822TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01008823 prepareSecondaryDisplay(ViewportType::EXTERNAL);
Garfield Tan888a6a42020-01-09 11:39:16 -08008824
Michael Wrighta9cf4192022-12-01 23:46:39 +00008825 prepareDisplay(ui::ROTATION_0);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008826 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008827 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008828
Josep del Río2d8c79a2023-01-23 19:33:50 +00008829 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008830
8831 NotifyMotionArgs motionArgs;
8832 processPosition(mapper, 100, 100);
8833 processSync(mapper);
8834
8835 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8836 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008837 ASSERT_EQ(ui::LogicalDisplayId::INVALID, motionArgs.displayId);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008838}
8839
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008840/**
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008841 * Ensure that the readTime is set to the SYN_REPORT value when processing touch events.
8842 */
8843TEST_F(MultiTouchInputMapperTest, Process_SendsReadTime) {
8844 addConfigurationProperty("touch.deviceType", "touchScreen");
8845 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008846 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008847
Michael Wrighta9cf4192022-12-01 23:46:39 +00008848 prepareDisplay(ui::ROTATION_0);
Harry Cutts33476232023-01-30 19:57:29 +00008849 process(mapper, 10, /*readTime=*/11, EV_ABS, ABS_MT_TRACKING_ID, 1);
8850 process(mapper, 15, /*readTime=*/16, EV_ABS, ABS_MT_POSITION_X, 100);
8851 process(mapper, 20, /*readTime=*/21, EV_ABS, ABS_MT_POSITION_Y, 100);
8852 process(mapper, 25, /*readTime=*/26, EV_SYN, SYN_REPORT, 0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008853
8854 NotifyMotionArgs args;
8855 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8856 ASSERT_EQ(26, args.readTime);
8857
Harry Cutts33476232023-01-30 19:57:29 +00008858 process(mapper, 30, /*readTime=*/31, EV_ABS, ABS_MT_POSITION_X, 110);
8859 process(mapper, 30, /*readTime=*/32, EV_ABS, ABS_MT_POSITION_Y, 220);
8860 process(mapper, 30, /*readTime=*/33, EV_SYN, SYN_REPORT, 0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008861
8862 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8863 ASSERT_EQ(33, args.readTime);
8864}
8865
8866/**
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008867 * When the viewport is not active (isActive=false), the touch mapper should be disabled and the
8868 * events should not be delivered to the listener.
8869 */
8870TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreDropped) {
8871 addConfigurationProperty("touch.deviceType", "touchScreen");
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008872 // Don't set touch.enableForInactiveViewport to verify the default behavior.
Michael Wrighta9cf4192022-12-01 23:46:39 +00008873 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008874 /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008875 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008876 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008877 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008878
8879 NotifyMotionArgs motionArgs;
8880 processPosition(mapper, 100, 100);
8881 processSync(mapper);
8882
8883 mFakeListener->assertNotifyMotionWasNotCalled();
8884}
8885
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008886/**
8887 * When the viewport is not active (isActive=false) and touch.enableForInactiveViewport is true,
8888 * the touch mapper can process the events and the events can be delivered to the listener.
8889 */
8890TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreProcessed) {
8891 addConfigurationProperty("touch.deviceType", "touchScreen");
8892 addConfigurationProperty("touch.enableForInactiveViewport", "1");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008893 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008894 /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008895 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008896 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008897 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008898
8899 NotifyMotionArgs motionArgs;
8900 processPosition(mapper, 100, 100);
8901 processSync(mapper);
8902
8903 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8904 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8905}
8906
Josh Thielene986aed2023-06-01 14:17:30 +00008907/**
8908 * When the viewport is deactivated (isActive transitions from true to false),
8909 * and touch.enableForInactiveViewport is false, touches prior to the transition
8910 * should be cancelled.
8911 */
Garfield Tanc734e4f2021-01-15 20:01:39 -08008912TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_AbortTouches) {
8913 addConfigurationProperty("touch.deviceType", "touchScreen");
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008914 addConfigurationProperty("touch.enableForInactiveViewport", "0");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008915 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008916 /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008917 std::optional<DisplayViewport> optionalDisplayViewport =
8918 mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
8919 ASSERT_TRUE(optionalDisplayViewport.has_value());
8920 DisplayViewport displayViewport = *optionalDisplayViewport;
8921
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008922 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008923 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008924 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Garfield Tanc734e4f2021-01-15 20:01:39 -08008925
8926 // Finger down
8927 int32_t x = 100, y = 100;
8928 processPosition(mapper, x, y);
8929 processSync(mapper);
8930
8931 NotifyMotionArgs motionArgs;
8932 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8933 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8934
8935 // Deactivate display viewport
8936 displayViewport.isActive = false;
8937 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008938 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008939
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008940 // The ongoing touch should be canceled immediately
8941 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8942 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
8943
8944 // Finger move is ignored
Garfield Tanc734e4f2021-01-15 20:01:39 -08008945 x += 10, y += 10;
8946 processPosition(mapper, x, y);
8947 processSync(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008948 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
Garfield Tanc734e4f2021-01-15 20:01:39 -08008949
8950 // Reactivate display viewport
8951 displayViewport.isActive = true;
8952 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008953 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008954
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008955 // Finger move again starts new gesture
Garfield Tanc734e4f2021-01-15 20:01:39 -08008956 x += 10, y += 10;
8957 processPosition(mapper, x, y);
8958 processSync(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008959 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8960 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008961}
8962
Josh Thielene986aed2023-06-01 14:17:30 +00008963/**
8964 * When the viewport is deactivated (isActive transitions from true to false),
8965 * and touch.enableForInactiveViewport is true, touches prior to the transition
8966 * should not be cancelled.
8967 */
8968TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_TouchesNotAborted) {
8969 addConfigurationProperty("touch.deviceType", "touchScreen");
8970 addConfigurationProperty("touch.enableForInactiveViewport", "1");
8971 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
8972 /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
8973 std::optional<DisplayViewport> optionalDisplayViewport =
8974 mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
8975 ASSERT_TRUE(optionalDisplayViewport.has_value());
8976 DisplayViewport displayViewport = *optionalDisplayViewport;
8977
8978 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8979 prepareAxes(POSITION);
8980 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
8981
8982 // Finger down
8983 int32_t x = 100, y = 100;
8984 processPosition(mapper, x, y);
8985 processSync(mapper);
8986 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8987 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
8988
8989 // Deactivate display viewport
8990 displayViewport.isActive = false;
8991 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
8992 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8993
8994 // The ongoing touch should not be canceled
8995 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
8996
8997 // Finger move is not ignored
8998 x += 10, y += 10;
8999 processPosition(mapper, x, y);
9000 processSync(mapper);
9001 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9002 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
9003
9004 // Reactivate display viewport
9005 displayViewport.isActive = true;
9006 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
9007 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
9008
9009 // Finger move continues and does not start new gesture
9010 x += 10, y += 10;
9011 processPosition(mapper, x, y);
9012 processSync(mapper);
9013 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9014 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
9015}
9016
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06009017TEST_F(MultiTouchInputMapperTest, VideoFrames_ReceivedByListener) {
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06009018 prepareAxes(POSITION);
9019 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009020 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00009021 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06009022
9023 NotifyMotionArgs motionArgs;
9024 // Unrotated video frame
9025 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
9026 std::vector<TouchVideoFrame> frames{frame};
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009027 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06009028 processPosition(mapper, 100, 200);
9029 processSync(mapper);
9030 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9031 ASSERT_EQ(frames, motionArgs.videoFrames);
9032
9033 // Subsequent touch events should not have any videoframes
9034 // This is implemented separately in FakeEventHub,
9035 // but that should match the behaviour of TouchVideoDevice.
9036 processPosition(mapper, 200, 200);
9037 processSync(mapper);
9038 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9039 ASSERT_EQ(std::vector<TouchVideoFrame>(), motionArgs.videoFrames);
9040}
9041
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009042TEST_F(MultiTouchInputMapperTest, VideoFrames_AreNotRotated) {
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009043 prepareAxes(POSITION);
9044 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00009045 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009046 // Unrotated video frame
9047 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
9048 NotifyMotionArgs motionArgs;
9049
9050 // Test all 4 orientations
Michael Wrighta9cf4192022-12-01 23:46:39 +00009051 for (ui::Rotation orientation : ftl::enum_range<ui::Rotation>()) {
Harry Cuttsc57cd3c2024-04-24 13:52:55 +00009052 SCOPED_TRACE(StringPrintf("Orientation %s", ftl::enum_string(orientation).c_str()));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009053 clearViewports();
9054 prepareDisplay(orientation);
9055 std::vector<TouchVideoFrame> frames{frame};
9056 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
9057 processPosition(mapper, 100, 200);
9058 processSync(mapper);
9059 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9060 ASSERT_EQ(frames, motionArgs.videoFrames);
9061 }
9062}
9063
9064TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_AreRotated) {
9065 prepareAxes(POSITION);
9066 addConfigurationProperty("touch.deviceType", "touchScreen");
9067 // Since InputReader works in the un-rotated coordinate space, only devices that are not
9068 // orientation-aware are affected by display rotation.
9069 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00009070 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009071 // Unrotated video frame
9072 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
9073 NotifyMotionArgs motionArgs;
9074
9075 // Test all 4 orientations
Michael Wrighta9cf4192022-12-01 23:46:39 +00009076 for (ui::Rotation orientation : ftl::enum_range<ui::Rotation>()) {
Harry Cuttsc57cd3c2024-04-24 13:52:55 +00009077 SCOPED_TRACE(StringPrintf("Orientation %s", ftl::enum_string(orientation).c_str()));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009078 clearViewports();
9079 prepareDisplay(orientation);
9080 std::vector<TouchVideoFrame> frames{frame};
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009081 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009082 processPosition(mapper, 100, 200);
9083 processSync(mapper);
9084 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009085 // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction
9086 // compared to the display. This is so that when the window transform (which contains the
9087 // display rotation) is applied later by InputDispatcher, the coordinates end up in the
9088 // window's coordinate space.
9089 frames[0].rotate(getInverseRotation(orientation));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009090 ASSERT_EQ(frames, motionArgs.videoFrames);
lilinnan687e58f2022-07-19 16:00:50 +08009091
9092 // Release finger.
9093 processSync(mapper);
9094 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009095 }
9096}
9097
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009098TEST_F(MultiTouchInputMapperTest, VideoFrames_MultipleFramesAreNotRotated) {
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009099 prepareAxes(POSITION);
9100 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00009101 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009102 // Unrotated video frames. There's no rule that they must all have the same dimensions,
9103 // so mix these.
9104 TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
9105 TouchVideoFrame frame2(3, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {1, 3});
9106 TouchVideoFrame frame3(2, 2, {10, 20, 10, 0}, {1, 4});
9107 std::vector<TouchVideoFrame> frames{frame1, frame2, frame3};
9108 NotifyMotionArgs motionArgs;
9109
Michael Wrighta9cf4192022-12-01 23:46:39 +00009110 prepareDisplay(ui::ROTATION_90);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009111 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009112 processPosition(mapper, 100, 200);
9113 processSync(mapper);
9114 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009115 ASSERT_EQ(frames, motionArgs.videoFrames);
9116}
9117
9118TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_MultipleFramesAreRotated) {
9119 prepareAxes(POSITION);
9120 addConfigurationProperty("touch.deviceType", "touchScreen");
9121 // Since InputReader works in the un-rotated coordinate space, only devices that are not
9122 // orientation-aware are affected by display rotation.
9123 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00009124 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009125 // Unrotated video frames. There's no rule that they must all have the same dimensions,
9126 // so mix these.
9127 TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
9128 TouchVideoFrame frame2(3, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {1, 3});
9129 TouchVideoFrame frame3(2, 2, {10, 20, 10, 0}, {1, 4});
9130 std::vector<TouchVideoFrame> frames{frame1, frame2, frame3};
9131 NotifyMotionArgs motionArgs;
9132
Michael Wrighta9cf4192022-12-01 23:46:39 +00009133 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009134 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
9135 processPosition(mapper, 100, 200);
9136 processSync(mapper);
9137 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9138 std::for_each(frames.begin(), frames.end(), [](TouchVideoFrame& frame) {
9139 // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction
9140 // compared to the display. This is so that when the window transform (which contains the
9141 // display rotation) is applied later by InputDispatcher, the coordinates end up in the
9142 // window's coordinate space.
Michael Wrighta9cf4192022-12-01 23:46:39 +00009143 frame.rotate(getInverseRotation(ui::ROTATION_90));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009144 });
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009145 ASSERT_EQ(frames, motionArgs.videoFrames);
9146}
9147
Arthur Hung9da14732019-09-02 16:16:58 +08009148/**
9149 * If we had defined port associations, but the viewport is not ready, the touch device would be
9150 * expected to be disabled, and it should be enabled after the viewport has found.
9151 */
9152TEST_F(MultiTouchInputMapperTest, Configure_EnabledForAssociatedDisplay) {
Arthur Hung9da14732019-09-02 16:16:58 +08009153 constexpr uint8_t hdmi2 = 1;
9154 const std::string secondaryUniqueId = "uniqueId2";
Michael Wrightfe3de7d2020-07-02 19:05:30 +01009155 constexpr ViewportType type = ViewportType::EXTERNAL;
Arthur Hung9da14732019-09-02 16:16:58 +08009156
9157 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi2);
9158
9159 addConfigurationProperty("touch.deviceType", "touchScreen");
9160 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00009161 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung9da14732019-09-02 16:16:58 +08009162
9163 ASSERT_EQ(mDevice->isEnabled(), false);
9164
9165 // Add display on hdmi2, the device should be enabled and can receive touch event.
9166 prepareSecondaryDisplay(type, hdmi2);
9167 ASSERT_EQ(mDevice->isEnabled(), true);
9168
9169 // Send a touch event.
9170 processPosition(mapper, 100, 100);
9171 processSync(mapper);
9172
9173 NotifyMotionArgs args;
9174 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9175 ASSERT_EQ(SECONDARY_DISPLAY_ID, args.displayId);
9176}
9177
Arthur Hung421eb1c2020-01-16 00:09:42 +08009178TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleSingleTouch) {
Arthur Hung421eb1c2020-01-16 00:09:42 +08009179 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009180 prepareDisplay(ui::ROTATION_0);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009181 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009182 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung421eb1c2020-01-16 00:09:42 +08009183
9184 NotifyMotionArgs motionArgs;
9185
9186 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
9187 // finger down
9188 processId(mapper, 1);
9189 processPosition(mapper, x1, y1);
9190 processSync(mapper);
9191 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9192 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009193 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009194
9195 // finger move
9196 processId(mapper, 1);
9197 processPosition(mapper, x2, y2);
9198 processSync(mapper);
9199 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9200 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009201 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009202
9203 // finger up.
9204 processId(mapper, -1);
9205 processSync(mapper);
9206 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9207 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009208 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009209
9210 // new finger down
9211 processId(mapper, 1);
9212 processPosition(mapper, x3, y3);
9213 processSync(mapper);
9214 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9215 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009216 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009217}
9218
9219/**
arthurhungcc7f9802020-04-30 17:55:40 +08009220 * Test single touch should be canceled when received the MT_TOOL_PALM event, and the following
9221 * MOVE and UP events should be ignored.
Arthur Hung421eb1c2020-01-16 00:09:42 +08009222 */
arthurhungcc7f9802020-04-30 17:55:40 +08009223TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_SinglePointer) {
Arthur Hung421eb1c2020-01-16 00:09:42 +08009224 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009225 prepareDisplay(ui::ROTATION_0);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009226 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009227 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung421eb1c2020-01-16 00:09:42 +08009228
9229 NotifyMotionArgs motionArgs;
9230
9231 // default tool type is finger
9232 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
arthurhungcc7f9802020-04-30 17:55:40 +08009233 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009234 processPosition(mapper, x1, y1);
9235 processSync(mapper);
9236 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9237 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009238 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009239
9240 // Tool changed to MT_TOOL_PALM expect sending the cancel event.
9241 processToolType(mapper, MT_TOOL_PALM);
9242 processSync(mapper);
9243 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9244 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9245
9246 // Ignore the following MOVE and UP events if had detect a palm event.
arthurhungcc7f9802020-04-30 17:55:40 +08009247 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009248 processPosition(mapper, x2, y2);
9249 processSync(mapper);
9250 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9251
9252 // finger up.
arthurhungcc7f9802020-04-30 17:55:40 +08009253 processId(mapper, INVALID_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009254 processSync(mapper);
9255 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9256
9257 // new finger down
arthurhungcc7f9802020-04-30 17:55:40 +08009258 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009259 processToolType(mapper, MT_TOOL_FINGER);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009260 processPosition(mapper, x3, y3);
9261 processSync(mapper);
9262 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9263 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009264 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009265}
9266
arthurhungbf89a482020-04-17 17:37:55 +08009267/**
arthurhungcc7f9802020-04-30 17:55:40 +08009268 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event from some finger,
9269 * and the rest active fingers could still be allowed to receive the events
arthurhungbf89a482020-04-17 17:37:55 +08009270 */
arthurhungcc7f9802020-04-30 17:55:40 +08009271TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_TwoPointers) {
arthurhungbf89a482020-04-17 17:37:55 +08009272 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009273 prepareDisplay(ui::ROTATION_0);
arthurhungbf89a482020-04-17 17:37:55 +08009274 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009275 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungbf89a482020-04-17 17:37:55 +08009276
9277 NotifyMotionArgs motionArgs;
9278
9279 // default tool type is finger
arthurhungcc7f9802020-04-30 17:55:40 +08009280 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220;
9281 processId(mapper, FIRST_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009282 processPosition(mapper, x1, y1);
9283 processSync(mapper);
9284 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9285 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009286 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungbf89a482020-04-17 17:37:55 +08009287
9288 // Second finger down.
arthurhungcc7f9802020-04-30 17:55:40 +08009289 processSlot(mapper, SECOND_SLOT);
9290 processId(mapper, SECOND_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009291 processPosition(mapper, x2, y2);
arthurhungcc7f9802020-04-30 17:55:40 +08009292 processSync(mapper);
9293 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009294 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009295 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009296
9297 // If the tool type of the first finger changes to MT_TOOL_PALM,
9298 // we expect to receive ACTION_POINTER_UP with cancel flag.
9299 processSlot(mapper, FIRST_SLOT);
9300 processId(mapper, FIRST_TRACKING_ID);
9301 processToolType(mapper, MT_TOOL_PALM);
9302 processSync(mapper);
9303 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009304 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009305 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9306
9307 // The following MOVE events of second finger should be processed.
9308 processSlot(mapper, SECOND_SLOT);
9309 processId(mapper, SECOND_TRACKING_ID);
9310 processPosition(mapper, x2 + 1, y2 + 1);
9311 processSync(mapper);
9312 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9313 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009314 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009315
9316 // First finger up. It used to be in palm mode, and we already generated ACTION_POINTER_UP for
9317 // it. Second finger receive move.
9318 processSlot(mapper, FIRST_SLOT);
9319 processId(mapper, INVALID_TRACKING_ID);
9320 processSync(mapper);
9321 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9322 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009323 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009324
9325 // Second finger keeps moving.
9326 processSlot(mapper, SECOND_SLOT);
9327 processId(mapper, SECOND_TRACKING_ID);
9328 processPosition(mapper, x2 + 2, y2 + 2);
9329 processSync(mapper);
9330 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9331 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009332 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009333
9334 // Second finger up.
9335 processId(mapper, INVALID_TRACKING_ID);
9336 processSync(mapper);
9337 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9338 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9339 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9340}
9341
9342/**
9343 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event, if only 1 finger
9344 * is active, it should send CANCEL after receiving the MT_TOOL_PALM event.
9345 */
9346TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_ShouldCancelWhenAllTouchIsPalm) {
9347 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009348 prepareDisplay(ui::ROTATION_0);
arthurhungcc7f9802020-04-30 17:55:40 +08009349 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009350 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungcc7f9802020-04-30 17:55:40 +08009351
9352 NotifyMotionArgs motionArgs;
9353
9354 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
9355 // First finger down.
9356 processId(mapper, FIRST_TRACKING_ID);
9357 processPosition(mapper, x1, y1);
9358 processSync(mapper);
9359 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9360 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009361 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009362
9363 // Second finger down.
9364 processSlot(mapper, SECOND_SLOT);
9365 processId(mapper, SECOND_TRACKING_ID);
9366 processPosition(mapper, x2, y2);
arthurhungbf89a482020-04-17 17:37:55 +08009367 processSync(mapper);
9368 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009369 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009370 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungbf89a482020-04-17 17:37:55 +08009371
arthurhungcc7f9802020-04-30 17:55:40 +08009372 // If the tool type of the first finger changes to MT_TOOL_PALM,
9373 // we expect to receive ACTION_POINTER_UP with cancel flag.
9374 processSlot(mapper, FIRST_SLOT);
9375 processId(mapper, FIRST_TRACKING_ID);
9376 processToolType(mapper, MT_TOOL_PALM);
9377 processSync(mapper);
9378 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009379 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009380 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9381
9382 // Second finger keeps moving.
9383 processSlot(mapper, SECOND_SLOT);
9384 processId(mapper, SECOND_TRACKING_ID);
9385 processPosition(mapper, x2 + 1, y2 + 1);
9386 processSync(mapper);
9387 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9388 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9389
9390 // second finger becomes palm, receive cancel due to only 1 finger is active.
9391 processId(mapper, SECOND_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009392 processToolType(mapper, MT_TOOL_PALM);
9393 processSync(mapper);
9394 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9395 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9396
arthurhungcc7f9802020-04-30 17:55:40 +08009397 // third finger down.
9398 processSlot(mapper, THIRD_SLOT);
9399 processId(mapper, THIRD_TRACKING_ID);
9400 processToolType(mapper, MT_TOOL_FINGER);
arthurhungbf89a482020-04-17 17:37:55 +08009401 processPosition(mapper, x3, y3);
9402 processSync(mapper);
arthurhungbf89a482020-04-17 17:37:55 +08009403 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9404 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009405 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009406 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009407
9408 // third finger move
9409 processId(mapper, THIRD_TRACKING_ID);
9410 processPosition(mapper, x3 + 1, y3 + 1);
9411 processSync(mapper);
9412 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9413 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9414
9415 // first finger up, third finger receive move.
9416 processSlot(mapper, FIRST_SLOT);
9417 processId(mapper, INVALID_TRACKING_ID);
9418 processSync(mapper);
9419 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9420 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009421 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009422
9423 // second finger up, third finger receive move.
9424 processSlot(mapper, SECOND_SLOT);
9425 processId(mapper, INVALID_TRACKING_ID);
9426 processSync(mapper);
9427 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9428 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009429 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009430
9431 // third finger up.
9432 processSlot(mapper, THIRD_SLOT);
9433 processId(mapper, INVALID_TRACKING_ID);
9434 processSync(mapper);
9435 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9436 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9437 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9438}
9439
9440/**
9441 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event from some finger,
9442 * and the active finger could still be allowed to receive the events
9443 */
9444TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_KeepFirstPointer) {
9445 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009446 prepareDisplay(ui::ROTATION_0);
arthurhungcc7f9802020-04-30 17:55:40 +08009447 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009448 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungcc7f9802020-04-30 17:55:40 +08009449
9450 NotifyMotionArgs motionArgs;
9451
9452 // default tool type is finger
9453 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220;
9454 processId(mapper, FIRST_TRACKING_ID);
9455 processPosition(mapper, x1, y1);
9456 processSync(mapper);
9457 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9458 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009459 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009460
9461 // Second finger down.
9462 processSlot(mapper, SECOND_SLOT);
9463 processId(mapper, SECOND_TRACKING_ID);
9464 processPosition(mapper, x2, y2);
9465 processSync(mapper);
9466 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009467 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009468 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009469
9470 // If the tool type of the second finger changes to MT_TOOL_PALM,
9471 // we expect to receive ACTION_POINTER_UP with cancel flag.
9472 processId(mapper, SECOND_TRACKING_ID);
9473 processToolType(mapper, MT_TOOL_PALM);
9474 processSync(mapper);
9475 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009476 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009477 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9478
9479 // The following MOVE event should be processed.
9480 processSlot(mapper, FIRST_SLOT);
9481 processId(mapper, FIRST_TRACKING_ID);
9482 processPosition(mapper, x1 + 1, y1 + 1);
9483 processSync(mapper);
9484 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9485 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009486 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009487
9488 // second finger up.
9489 processSlot(mapper, SECOND_SLOT);
9490 processId(mapper, INVALID_TRACKING_ID);
9491 processSync(mapper);
9492 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9493 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9494
9495 // first finger keep moving
9496 processSlot(mapper, FIRST_SLOT);
9497 processId(mapper, FIRST_TRACKING_ID);
9498 processPosition(mapper, x1 + 2, y1 + 2);
9499 processSync(mapper);
9500 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9501 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9502
9503 // first finger up.
9504 processId(mapper, INVALID_TRACKING_ID);
9505 processSync(mapper);
9506 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9507 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9508 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
arthurhungbf89a482020-04-17 17:37:55 +08009509}
9510
Arthur Hung9ad18942021-06-19 02:04:46 +00009511/**
9512 * Test multi-touch should sent ACTION_POINTER_UP/ACTION_UP when received the INVALID_TRACKING_ID,
9513 * to prevent the driver side may send unexpected data after set tracking id as INVALID_TRACKING_ID
9514 * cause slot be valid again.
9515 */
9516TEST_F(MultiTouchInputMapperTest, Process_MultiTouch_WithInvalidTrackingId) {
9517 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009518 prepareDisplay(ui::ROTATION_0);
Arthur Hung9ad18942021-06-19 02:04:46 +00009519 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009520 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung9ad18942021-06-19 02:04:46 +00009521
9522 NotifyMotionArgs motionArgs;
9523
9524 constexpr int32_t x1 = 100, y1 = 200, x2 = 0, y2 = 0;
9525 // First finger down.
9526 processId(mapper, FIRST_TRACKING_ID);
9527 processPosition(mapper, x1, y1);
9528 processPressure(mapper, RAW_PRESSURE_MAX);
9529 processSync(mapper);
9530 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9531 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009532 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009533
9534 // First finger move.
9535 processId(mapper, FIRST_TRACKING_ID);
9536 processPosition(mapper, x1 + 1, y1 + 1);
9537 processPressure(mapper, RAW_PRESSURE_MAX);
9538 processSync(mapper);
9539 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9540 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009541 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009542
9543 // Second finger down.
9544 processSlot(mapper, SECOND_SLOT);
9545 processId(mapper, SECOND_TRACKING_ID);
9546 processPosition(mapper, x2, y2);
9547 processPressure(mapper, RAW_PRESSURE_MAX);
9548 processSync(mapper);
9549 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009550 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009551 ASSERT_EQ(uint32_t(2), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009552
9553 // second finger up with some unexpected data.
9554 processSlot(mapper, SECOND_SLOT);
9555 processId(mapper, INVALID_TRACKING_ID);
9556 processPosition(mapper, x2, y2);
9557 processSync(mapper);
9558 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009559 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009560 ASSERT_EQ(uint32_t(2), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009561
9562 // first finger up with some unexpected data.
9563 processSlot(mapper, FIRST_SLOT);
9564 processId(mapper, INVALID_TRACKING_ID);
9565 processPosition(mapper, x2, y2);
9566 processPressure(mapper, RAW_PRESSURE_MAX);
9567 processSync(mapper);
9568 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9569 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009570 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009571}
9572
Arpit Singh4b4a4572023-11-24 18:19:56 +00009573TEST_F(MultiTouchInputMapperTest, Reset_RepopulatesMultiTouchState) {
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009574 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009575 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009576 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009577 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009578
9579 // First finger down.
Arpit Singh4b4a4572023-11-24 18:19:56 +00009580 constexpr int32_t x1 = 100, y1 = 200, x2 = 300, y2 = 400;
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009581 processId(mapper, FIRST_TRACKING_ID);
Arpit Singh4b4a4572023-11-24 18:19:56 +00009582 processPosition(mapper, x1, y1);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009583 processPressure(mapper, RAW_PRESSURE_MAX);
9584 processSync(mapper);
9585 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9586 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
9587
9588 // Second finger down.
9589 processSlot(mapper, SECOND_SLOT);
9590 processId(mapper, SECOND_TRACKING_ID);
Arpit Singh4b4a4572023-11-24 18:19:56 +00009591 processPosition(mapper, x2, y2);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009592 processPressure(mapper, RAW_PRESSURE_MAX);
9593 processSync(mapper);
9594 ASSERT_NO_FATAL_FAILURE(
9595 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(ACTION_POINTER_1_DOWN)));
9596
Arpit Singh4b4a4572023-11-24 18:19:56 +00009597 // Set MT Slot state to be repopulated for the required slots
9598 std::vector<int32_t> mtSlotValues(RAW_SLOT_MAX + 1, -1);
9599 mtSlotValues[0] = FIRST_TRACKING_ID;
9600 mtSlotValues[1] = SECOND_TRACKING_ID;
9601 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_TRACKING_ID, mtSlotValues);
9602
9603 mtSlotValues[0] = x1;
9604 mtSlotValues[1] = x2;
9605 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_POSITION_X, mtSlotValues);
9606
9607 mtSlotValues[0] = y1;
9608 mtSlotValues[1] = y2;
9609 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_POSITION_Y, mtSlotValues);
9610
9611 mtSlotValues[0] = RAW_PRESSURE_MAX;
9612 mtSlotValues[1] = RAW_PRESSURE_MAX;
9613 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_PRESSURE, mtSlotValues);
9614
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009615 // Reset the mapper. When the mapper is reset, we expect the current multi-touch state to be
Arpit Singh4b4a4572023-11-24 18:19:56 +00009616 // repopulated. Resetting should cancel the ongoing gesture.
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00009617 resetMapper(mapper, ARBITRARY_TIME);
9618 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9619 WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009620
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009621 // Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
9622 // the existing touch state to generate a down event.
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009623 processPosition(mapper, 301, 302);
9624 processSync(mapper);
9625 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9626 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPressure(1.f))));
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009627 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9628 AllOf(WithMotionAction(ACTION_POINTER_1_DOWN), WithPressure(1.f))));
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009629
9630 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9631}
9632
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009633TEST_F(MultiTouchInputMapperTest, Reset_PreservesLastTouchState_NoPointersDown) {
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009634 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009635 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009636 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009637 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009638
9639 // First finger touches down and releases.
9640 processId(mapper, FIRST_TRACKING_ID);
9641 processPosition(mapper, 100, 200);
9642 processPressure(mapper, RAW_PRESSURE_MAX);
9643 processSync(mapper);
9644 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9645 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
9646 processId(mapper, INVALID_TRACKING_ID);
9647 processSync(mapper);
9648 ASSERT_NO_FATAL_FAILURE(
9649 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
9650
9651 // Reset the mapper. When the mapper is reset, we expect it to restore the latest
9652 // raw state where no pointers are down.
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00009653 resetMapper(mapper, ARBITRARY_TIME);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009654 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9655
9656 // Send an empty sync frame. Since there are no pointers, no events are generated.
9657 processSync(mapper);
9658 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9659}
9660
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009661TEST_F(MultiTouchInputMapperTest, StylusSourceIsAddedDynamicallyFromToolType) {
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009662 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009663 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009664 prepareAxes(POSITION | ID | SLOT | PRESSURE | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009665 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009666 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009667
9668 // Even if the device supports reporting the ABS_MT_TOOL_TYPE axis, which could give it the
9669 // ability to report MT_TOOL_PEN, we do not report the device as coming from a stylus source.
9670 // Due to limitations in the evdev protocol, we cannot say for certain that a device is capable
9671 // of reporting stylus events just because it supports ABS_MT_TOOL_TYPE.
9672 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
9673
9674 // However, if the device ever ends up reporting an event with MT_TOOL_PEN, it should be
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009675 // reported with the stylus source.
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009676 processId(mapper, FIRST_TRACKING_ID);
9677 processToolType(mapper, MT_TOOL_PEN);
9678 processPosition(mapper, 100, 200);
9679 processPressure(mapper, RAW_PRESSURE_MAX);
9680 processSync(mapper);
9681 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9682 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
9683 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009684 WithToolType(ToolType::STYLUS))));
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009685
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009686 // Now that we know the device supports styluses, ensure that the device is re-configured with
9687 // the stylus source.
9688 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, mapper.getSources());
9689 {
9690 const auto& devices = mReader->getInputDevices();
9691 auto deviceInfo =
9692 std::find_if(devices.begin(), devices.end(),
9693 [](const InputDeviceInfo& info) { return info.getId() == DEVICE_ID; });
9694 LOG_ALWAYS_FATAL_IF(deviceInfo == devices.end(), "Cannot find InputDevice");
9695 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, deviceInfo->getSources());
9696 }
9697
9698 // Ensure the device was not reset to prevent interruptions of any ongoing gestures.
9699 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
9700
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009701 processId(mapper, INVALID_TRACKING_ID);
9702 processSync(mapper);
9703 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9704 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
9705 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009706 WithToolType(ToolType::STYLUS))));
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009707}
9708
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009709// --- MultiTouchInputMapperTest_ExternalDevice ---
9710
9711class MultiTouchInputMapperTest_ExternalDevice : public MultiTouchInputMapperTest {
9712protected:
Chris Yea52ade12020-08-27 16:49:20 -07009713 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL); }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009714};
9715
9716/**
9717 * Expect fallback to internal viewport if device is external and external viewport is not present.
9718 */
9719TEST_F(MultiTouchInputMapperTest_ExternalDevice, Viewports_Fallback) {
9720 prepareAxes(POSITION);
9721 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009722 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00009723 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009724
9725 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
9726
9727 NotifyMotionArgs motionArgs;
9728
9729 // Expect the event to be sent to the internal viewport,
9730 // because an external viewport is not present.
9731 processPosition(mapper, 100, 100);
9732 processSync(mapper);
9733 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009734 ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, motionArgs.displayId);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009735
9736 // Expect the event to be sent to the external viewport if it is present.
Michael Wrightfe3de7d2020-07-02 19:05:30 +01009737 prepareSecondaryDisplay(ViewportType::EXTERNAL);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009738 processPosition(mapper, 100, 100);
9739 processSync(mapper);
9740 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9741 ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
9742}
Arthur Hung4197f6b2020-03-16 15:39:59 +08009743
Prabir Pradhan3ed7e352024-05-03 23:59:43 +00009744// TODO(b/281840344): Remove the test when the old touchpad stack is removed. It is currently
9745// unclear what the behavior of the touchpad logic in TouchInputMapper should do after the
9746// PointerChoreographer refactor.
9747TEST_F(MultiTouchInputMapperTest, DISABLED_Process_TouchpadPointer) {
Harry Cutts8722be92024-04-05 14:46:05 +00009748 // prepare device
Michael Wrighta9cf4192022-12-01 23:46:39 +00009749 prepareDisplay(ui::ROTATION_0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009750 prepareAxes(POSITION | ID | SLOT);
9751 mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
9752 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00009753 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009754 // run uncaptured pointer tests - pushes out generic events
9755 // FINGER 0 DOWN
9756 processId(mapper, 3);
9757 processPosition(mapper, 100, 100);
9758 processKey(mapper, BTN_TOUCH, 1);
9759 processSync(mapper);
9760
9761 // start at (100,100), cursor should be at (0,0) * scale
9762 NotifyMotionArgs args;
9763 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9764 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
9765 ASSERT_NO_FATAL_FAILURE(
9766 assertPointerCoords(args.pointerCoords[0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
9767
9768 // FINGER 0 MOVE
9769 processPosition(mapper, 200, 200);
9770 processSync(mapper);
9771
9772 // compute scaling to help with touch position checking
9773 float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
9774 float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
9775 float scale =
9776 mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
9777
9778 // translate from (100,100) -> (200,200), cursor should have changed to (100,100) * scale)
9779 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9780 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
9781 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], 100 * scale, 100 * scale, 0,
9782 0, 0, 0, 0, 0, 0, 0));
LiZhihong758eb562022-11-03 15:28:29 +08009783
9784 // BUTTON DOWN
9785 processKey(mapper, BTN_LEFT, 1);
9786 processSync(mapper);
9787
9788 // touchinputmapper design sends a move before button press
9789 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9790 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
9791 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9792 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, args.action);
9793
9794 // BUTTON UP
9795 processKey(mapper, BTN_LEFT, 0);
9796 processSync(mapper);
9797
9798 // touchinputmapper design sends a move after button release
9799 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9800 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, args.action);
9801 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9802 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009803}
9804
Harry Cutts8722be92024-04-05 14:46:05 +00009805TEST_F(MultiTouchInputMapperTest, Touchpad_GetSources) {
Michael Wrighta9cf4192022-12-01 23:46:39 +00009806 prepareDisplay(ui::ROTATION_0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009807 prepareAxes(POSITION | ID | SLOT);
9808 mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
Hiroki Sato25040232024-02-22 17:21:22 +09009809 mFakePolicy->setPointerCapture(/*window=*/nullptr);
Arpit Singha8c236b2023-04-25 13:56:05 +00009810 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009811
Josep del Río2d8c79a2023-01-23 19:33:50 +00009812 // uncaptured touchpad should be a pointer device
9813 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009814}
9815
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009816// --- BluetoothMultiTouchInputMapperTest ---
9817
9818class BluetoothMultiTouchInputMapperTest : public MultiTouchInputMapperTest {
9819protected:
9820 void SetUp() override {
9821 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL, BUS_BLUETOOTH);
9822 }
9823};
9824
9825TEST_F(BluetoothMultiTouchInputMapperTest, TimestampSmoothening) {
9826 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009827 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009828 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009829 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009830
9831 nsecs_t kernelEventTime = ARBITRARY_TIME;
9832 nsecs_t expectedEventTime = ARBITRARY_TIME;
9833 // Touch down.
9834 processId(mapper, FIRST_TRACKING_ID);
9835 processPosition(mapper, 100, 200);
9836 processPressure(mapper, RAW_PRESSURE_MAX);
9837 processSync(mapper, ARBITRARY_TIME);
9838 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9839 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithEventTime(ARBITRARY_TIME))));
9840
9841 // Process several events that come in quick succession, according to their timestamps.
9842 for (int i = 0; i < 3; i++) {
9843 constexpr static nsecs_t delta = ms2ns(1);
9844 static_assert(delta < MIN_BLUETOOTH_TIMESTAMP_DELTA);
9845 kernelEventTime += delta;
9846 expectedEventTime += MIN_BLUETOOTH_TIMESTAMP_DELTA;
9847
9848 processPosition(mapper, 101 + i, 201 + i);
9849 processSync(mapper, kernelEventTime);
9850 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9851 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
9852 WithEventTime(expectedEventTime))));
9853 }
9854
9855 // Release the touch.
9856 processId(mapper, INVALID_TRACKING_ID);
9857 processPressure(mapper, RAW_PRESSURE_MIN);
9858 processSync(mapper, ARBITRARY_TIME + ms2ns(50));
9859 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9860 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
9861 WithEventTime(ARBITRARY_TIME + ms2ns(50)))));
9862}
9863
9864// --- MultiTouchPointerModeTest ---
9865
HQ Liue6983c72022-04-19 22:14:56 +00009866class MultiTouchPointerModeTest : public MultiTouchInputMapperTest {
9867protected:
9868 float mPointerMovementScale;
9869 float mPointerXZoomScale;
9870 void preparePointerMode(int xAxisResolution, int yAxisResolution) {
9871 addConfigurationProperty("touch.deviceType", "pointer");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009872 prepareDisplay(ui::ROTATION_0);
HQ Liue6983c72022-04-19 22:14:56 +00009873
9874 prepareAxes(POSITION);
9875 prepareAbsoluteAxisResolution(xAxisResolution, yAxisResolution);
9876 // In order to enable swipe and freeform gesture in pointer mode, pointer capture
9877 // needs to be disabled, and the pointer gesture needs to be enabled.
Hiroki Sato25040232024-02-22 17:21:22 +09009878 mFakePolicy->setPointerCapture(/*window=*/nullptr);
HQ Liue6983c72022-04-19 22:14:56 +00009879 mFakePolicy->setPointerGestureEnabled(true);
HQ Liue6983c72022-04-19 22:14:56 +00009880
9881 float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
9882 float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
9883 mPointerMovementScale =
9884 mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
9885 mPointerXZoomScale =
9886 mFakePolicy->getPointerGestureZoomSpeedRatio() * displayDiagonal / rawDiagonal;
9887 }
9888
9889 void prepareAbsoluteAxisResolution(int xAxisResolution, int yAxisResolution) {
9890 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX,
9891 /*flat*/ 0,
9892 /*fuzz*/ 0, /*resolution*/ xAxisResolution);
9893 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX,
9894 /*flat*/ 0,
9895 /*fuzz*/ 0, /*resolution*/ yAxisResolution);
9896 }
9897};
9898
9899/**
9900 * Two fingers down on a pointer mode touch pad. The width
9901 * of the two finger is larger than 1/4 of the touch pack diagnal length. However, it
9902 * is smaller than the fixed min physical length 30mm. Two fingers' distance must
9903 * be greater than the both value to be freeform gesture, so that after two
9904 * fingers start to move downwards, the gesture should be swipe.
9905 */
9906TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthSwipe) {
9907 // The min freeform gesture width is 25units/mm x 30mm = 750
9908 // which is greater than fraction of the diagnal length of the touchpad (349).
9909 // Thus, MaxSwipWidth is 750.
Harry Cutts33476232023-01-30 19:57:29 +00009910 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +00009911 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009912 NotifyMotionArgs motionArgs;
9913
9914 // Two fingers down at once.
9915 // The two fingers are 450 units apart, expects the current gesture to be PRESS
9916 // Pointer's initial position is used the [0,0] coordinate.
9917 int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125;
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_DOWN, 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::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009932 ASSERT_NO_FATAL_FAILURE(
9933 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9934
9935 // It should be recognized as a SWIPE gesture when two fingers start to move down,
9936 // that there should be 1 pointer.
9937 int32_t movingDistance = 200;
9938 y1 += movingDistance;
9939 y2 += movingDistance;
9940
9941 processId(mapper, FIRST_TRACKING_ID);
9942 processPosition(mapper, x1, y1);
9943 processMTSync(mapper);
9944 processId(mapper, SECOND_TRACKING_ID);
9945 processPosition(mapper, x2, y2);
9946 processMTSync(mapper);
9947 processSync(mapper);
9948
9949 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009950 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009951 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009952 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009953 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009954 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
9955 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9956 0, 0, 0, 0));
9957}
9958
9959/**
9960 * Two fingers down on a pointer mode touch pad. The width of the two finger is larger
9961 * than the minimum freeform gesture width, 30mm. However, it is smaller than 1/4 of
9962 * the touch pack diagnal length. Two fingers' distance must be greater than the both
9963 * value to be freeform gesture, so that after two fingers start to move downwards,
9964 * the gesture should be swipe.
9965 */
9966TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthLowResolutionSwipe) {
9967 // The min freeform gesture width is 5units/mm x 30mm = 150
9968 // which is greater than fraction of the diagnal length of the touchpad (349).
9969 // Thus, MaxSwipWidth is the fraction of the diagnal length, 349.
Harry Cutts33476232023-01-30 19:57:29 +00009970 preparePointerMode(/*xResolution=*/5, /*yResolution=*/5);
Arpit Singha8c236b2023-04-25 13:56:05 +00009971 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009972 NotifyMotionArgs motionArgs;
9973
9974 // Two fingers down at once.
9975 // The two fingers are 250 units apart, expects the current gesture to be PRESS
9976 // Pointer's initial position is used the [0,0] coordinate.
9977 int32_t x1 = 100, y1 = 125, x2 = 350, y2 = 125;
9978
9979 processId(mapper, FIRST_TRACKING_ID);
9980 processPosition(mapper, x1, y1);
9981 processMTSync(mapper);
9982 processId(mapper, SECOND_TRACKING_ID);
9983 processPosition(mapper, x2, y2);
9984 processMTSync(mapper);
9985 processSync(mapper);
9986
9987 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009988 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009989 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009990 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009991 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009992 ASSERT_NO_FATAL_FAILURE(
9993 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9994
9995 // It should be recognized as a SWIPE gesture when two fingers start to move down,
9996 // and there should be 1 pointer.
9997 int32_t movingDistance = 200;
9998 y1 += movingDistance;
9999 y2 += movingDistance;
10000
10001 processId(mapper, FIRST_TRACKING_ID);
10002 processPosition(mapper, x1, y1);
10003 processMTSync(mapper);
10004 processId(mapper, SECOND_TRACKING_ID);
10005 processPosition(mapper, x2, y2);
10006 processMTSync(mapper);
10007 processSync(mapper);
10008
10009 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010010 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010011 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010012 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +000010013 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +000010014 // New coordinate is the scaled relative coordinate from the initial coordinate.
10015 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
10016 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
10017 0, 0, 0, 0));
10018}
10019
10020/**
10021 * Touch the touch pad with two fingers with a distance wider than the minimum freeform
10022 * gesture width and 1/4 of the diagnal length of the touchpad. Expect to receive
10023 * freeform gestures after two fingers start to move downwards.
10024 */
10025TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthFreeform) {
Harry Cutts33476232023-01-30 19:57:29 +000010026 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +000010027 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +000010028
10029 NotifyMotionArgs motionArgs;
10030
10031 // Two fingers down at once. Wider than the max swipe width.
10032 // The gesture is expected to be PRESS, then transformed to FREEFORM
10033 int32_t x1 = 100, y1 = 125, x2 = 900, y2 = 125;
10034
10035 processId(mapper, FIRST_TRACKING_ID);
10036 processPosition(mapper, x1, y1);
10037 processMTSync(mapper);
10038 processId(mapper, SECOND_TRACKING_ID);
10039 processPosition(mapper, x2, y2);
10040 processMTSync(mapper);
10041 processSync(mapper);
10042
10043 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010044 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010045 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010046 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +000010047 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +000010048 // One pointer for PRESS, and its coordinate is used as the origin for pointer coordinates.
10049 ASSERT_NO_FATAL_FAILURE(
10050 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
10051
10052 int32_t movingDistance = 200;
10053
10054 // Move two fingers down, expect a cancel event because gesture is changing to freeform,
10055 // then two down events for two pointers.
10056 y1 += movingDistance;
10057 y2 += movingDistance;
10058
10059 processId(mapper, FIRST_TRACKING_ID);
10060 processPosition(mapper, x1, y1);
10061 processMTSync(mapper);
10062 processId(mapper, SECOND_TRACKING_ID);
10063 processPosition(mapper, x2, y2);
10064 processMTSync(mapper);
10065 processSync(mapper);
10066
10067 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
10068 // The previous PRESS gesture is cancelled, because it is transformed to freeform
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010069 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010070 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
10071 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010072 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010073 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010074 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
10075 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010076 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +000010077 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010078 ASSERT_EQ(2U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010079 ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN, motionArgs.action & AMOTION_EVENT_ACTION_MASK);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010080 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +000010081 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +000010082 // Two pointers' scaled relative coordinates from their initial centroid.
10083 // Initial y coordinates are 0 as y1 and y2 have the same value.
10084 float cookedX1 = (x1 - x2) / 2 * mPointerXZoomScale;
10085 float cookedX2 = (x2 - x1) / 2 * mPointerXZoomScale;
10086 // When pointers move, the new coordinates equal to the initial coordinates plus
10087 // scaled moving distance.
10088 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
10089 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
10090 0, 0, 0, 0));
10091 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], cookedX2,
10092 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
10093 0, 0, 0, 0));
10094
10095 // Move two fingers down again, expect one MOVE motion event.
10096 y1 += movingDistance;
10097 y2 += movingDistance;
10098
10099 processId(mapper, FIRST_TRACKING_ID);
10100 processPosition(mapper, x1, y1);
10101 processMTSync(mapper);
10102 processId(mapper, SECOND_TRACKING_ID);
10103 processPosition(mapper, x2, y2);
10104 processMTSync(mapper);
10105 processSync(mapper);
10106
10107 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010108 ASSERT_EQ(2U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010109 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010110 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +000010111 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +000010112 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
10113 movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
10114 0, 0, 0, 0, 0));
10115 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], cookedX2,
10116 movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
10117 0, 0, 0, 0, 0));
10118}
10119
Harry Cutts39b7ca22022-10-05 15:55:48 +000010120TEST_F(MultiTouchPointerModeTest, TwoFingerSwipeOffsets) {
Harry Cutts33476232023-01-30 19:57:29 +000010121 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +000010122 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Harry Cutts39b7ca22022-10-05 15:55:48 +000010123 NotifyMotionArgs motionArgs;
10124
10125 // Place two fingers down.
10126 int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125;
10127
10128 processId(mapper, FIRST_TRACKING_ID);
10129 processPosition(mapper, x1, y1);
10130 processMTSync(mapper);
10131 processId(mapper, SECOND_TRACKING_ID);
10132 processPosition(mapper, x2, y2);
10133 processMTSync(mapper);
10134 processSync(mapper);
10135
10136 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010137 ASSERT_EQ(1U, motionArgs.getPointerCount());
Harry Cutts39b7ca22022-10-05 15:55:48 +000010138 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
10139 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
10140 ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET));
10141 ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET));
10142
10143 // Move the two fingers down and to the left.
10144 int32_t movingDistance = 200;
10145 x1 -= movingDistance;
10146 y1 += movingDistance;
10147 x2 -= movingDistance;
10148 y2 += movingDistance;
10149
10150 processId(mapper, FIRST_TRACKING_ID);
10151 processPosition(mapper, x1, y1);
10152 processMTSync(mapper);
10153 processId(mapper, SECOND_TRACKING_ID);
10154 processPosition(mapper, x2, y2);
10155 processMTSync(mapper);
10156 processSync(mapper);
10157
10158 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010159 ASSERT_EQ(1U, motionArgs.getPointerCount());
Harry Cutts39b7ca22022-10-05 15:55:48 +000010160 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
10161 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
10162 ASSERT_LT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET), 0);
10163 ASSERT_GT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET), 0);
10164}
10165
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010166TEST_F(MultiTouchPointerModeTest, WhenViewportActiveStatusChanged_PointerGestureIsReset) {
Harry Cutts33476232023-01-30 19:57:29 +000010167 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010168 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +000010169 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010170 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
10171
10172 // Start a stylus gesture.
10173 processKey(mapper, BTN_TOOL_PEN, 1);
10174 processId(mapper, FIRST_TRACKING_ID);
10175 processPosition(mapper, 100, 200);
10176 processSync(mapper);
10177 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10178 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
10179 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010180 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010181 // TODO(b/257078296): Pointer mode generates extra event.
10182 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10183 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
10184 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010185 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010186 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
10187
10188 // Make the viewport inactive. This will put the device in disabled mode, and the ongoing stylus
10189 // gesture should be disabled.
10190 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
10191 viewport->isActive = false;
10192 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +000010193 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010194 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10195 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
10196 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010197 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010198 // TODO(b/257078296): Pointer mode generates extra event.
10199 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10200 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
10201 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010202 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010203 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
10204}
10205
Arthur Hung6d5b4b22022-01-21 07:21:10 +000010206// --- JoystickInputMapperTest ---
10207
10208class JoystickInputMapperTest : public InputMapperTest {
10209protected:
10210 static const int32_t RAW_X_MIN;
10211 static const int32_t RAW_X_MAX;
10212 static const int32_t RAW_Y_MIN;
10213 static const int32_t RAW_Y_MAX;
10214
10215 void SetUp() override {
10216 InputMapperTest::SetUp(InputDeviceClass::JOYSTICK | InputDeviceClass::EXTERNAL);
10217 }
10218 void prepareAxes() {
10219 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
10220 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
10221 }
10222
10223 void processAxis(JoystickInputMapper& mapper, int32_t axis, int32_t value) {
10224 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, axis, value);
10225 }
10226
10227 void processSync(JoystickInputMapper& mapper) {
10228 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
10229 }
10230
Michael Wrighta9cf4192022-12-01 23:46:39 +000010231 void prepareVirtualDisplay(ui::Rotation orientation) {
Arthur Hung6d5b4b22022-01-21 07:21:10 +000010232 setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH,
10233 VIRTUAL_DISPLAY_HEIGHT, orientation, VIRTUAL_DISPLAY_UNIQUE_ID,
10234 NO_PORT, ViewportType::VIRTUAL);
10235 }
10236};
10237
10238const int32_t JoystickInputMapperTest::RAW_X_MIN = -32767;
10239const int32_t JoystickInputMapperTest::RAW_X_MAX = 32767;
10240const int32_t JoystickInputMapperTest::RAW_Y_MIN = -32767;
10241const int32_t JoystickInputMapperTest::RAW_Y_MAX = 32767;
10242
10243TEST_F(JoystickInputMapperTest, Configure_AssignsDisplayUniqueId) {
10244 prepareAxes();
Arpit Singhae876352023-04-26 14:16:50 +000010245 JoystickInputMapper& mapper = constructAndAddMapper<JoystickInputMapper>();
Arthur Hung6d5b4b22022-01-21 07:21:10 +000010246
10247 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID);
10248
Michael Wrighta9cf4192022-12-01 23:46:39 +000010249 prepareVirtualDisplay(ui::ROTATION_0);
Arthur Hung6d5b4b22022-01-21 07:21:10 +000010250
10251 // Send an axis event
10252 processAxis(mapper, ABS_X, 100);
10253 processSync(mapper);
10254
10255 NotifyMotionArgs args;
10256 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
10257 ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId);
10258
10259 // Send another axis event
10260 processAxis(mapper, ABS_Y, 100);
10261 processSync(mapper);
10262
10263 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
10264 ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId);
10265}
10266
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010267// --- PeripheralControllerTest ---
Chris Yee2b1e5c2021-03-10 22:45:12 -080010268
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010269class PeripheralControllerTest : public testing::Test {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010270protected:
10271 static const char* DEVICE_NAME;
10272 static const char* DEVICE_LOCATION;
10273 static const int32_t DEVICE_ID;
10274 static const int32_t DEVICE_GENERATION;
10275 static const int32_t DEVICE_CONTROLLER_NUMBER;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010276 static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010277 static const int32_t EVENTHUB_ID;
10278
10279 std::shared_ptr<FakeEventHub> mFakeEventHub;
10280 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010281 std::unique_ptr<TestInputListener> mFakeListener;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010282 std::unique_ptr<InstrumentedInputReader> mReader;
10283 std::shared_ptr<InputDevice> mDevice;
10284
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010285 virtual void SetUp(ftl::Flags<InputDeviceClass> classes) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010286 mFakeEventHub = std::make_unique<FakeEventHub>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010287 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010288 mFakeListener = std::make_unique<TestInputListener>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010289 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010290 *mFakeListener);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010291 mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes);
10292 }
10293
10294 void SetUp() override { SetUp(DEVICE_CLASSES); }
10295
10296 void TearDown() override {
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010297 mFakeListener.reset();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010298 mFakePolicy.clear();
10299 }
10300
Chris Yee2b1e5c2021-03-10 22:45:12 -080010301 std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
10302 const std::string& location, int32_t eventHubId,
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010303 ftl::Flags<InputDeviceClass> classes) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010304 InputDeviceIdentifier identifier;
10305 identifier.name = name;
10306 identifier.location = location;
10307 std::shared_ptr<InputDevice> device =
10308 std::make_shared<InputDevice>(mReader->getContext(), deviceId, DEVICE_GENERATION,
10309 identifier);
10310 mReader->pushNextDevice(device);
10311 mFakeEventHub->addDevice(eventHubId, name, classes);
10312 mReader->loopOnce();
10313 return device;
10314 }
10315
10316 template <class T, typename... Args>
10317 T& addControllerAndConfigure(Args... args) {
10318 T& controller = mDevice->addController<T>(EVENTHUB_ID, args...);
10319
10320 return controller;
10321 }
10322};
10323
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010324const char* PeripheralControllerTest::DEVICE_NAME = "device";
10325const char* PeripheralControllerTest::DEVICE_LOCATION = "BLUETOOTH";
10326const int32_t PeripheralControllerTest::DEVICE_ID = END_RESERVED_ID + 1000;
10327const int32_t PeripheralControllerTest::DEVICE_GENERATION = 2;
10328const int32_t PeripheralControllerTest::DEVICE_CONTROLLER_NUMBER = 0;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010329const ftl::Flags<InputDeviceClass> PeripheralControllerTest::DEVICE_CLASSES =
10330 ftl::Flags<InputDeviceClass>(0); // not needed for current tests
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010331const int32_t PeripheralControllerTest::EVENTHUB_ID = 1;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010332
10333// --- BatteryControllerTest ---
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010334class BatteryControllerTest : public PeripheralControllerTest {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010335protected:
10336 void SetUp() override {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010337 PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::BATTERY);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010338 }
10339};
10340
10341TEST_F(BatteryControllerTest, GetBatteryCapacity) {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010342 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010343
Harry Cuttsa5b71292022-11-28 12:56:17 +000010344 ASSERT_TRUE(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY));
10345 ASSERT_EQ(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY).value_or(-1),
10346 FakeEventHub::BATTERY_CAPACITY);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010347}
10348
10349TEST_F(BatteryControllerTest, GetBatteryStatus) {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010350 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010351
Harry Cuttsa5b71292022-11-28 12:56:17 +000010352 ASSERT_TRUE(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY));
10353 ASSERT_EQ(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY).value_or(-1),
10354 FakeEventHub::BATTERY_STATUS);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010355}
10356
10357// --- LightControllerTest ---
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010358class LightControllerTest : public PeripheralControllerTest {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010359protected:
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010360 void SetUp() override {
10361 PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::LIGHT);
10362 }
Chris Yee2b1e5c2021-03-10 22:45:12 -080010363};
10364
Chris Ye85758332021-05-16 23:05:17 -070010365TEST_F(LightControllerTest, MonoLight) {
10366 RawLightInfo infoMono = {.id = 1,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010367 .name = "mono_light",
Chris Ye85758332021-05-16 23:05:17 -070010368 .maxBrightness = 255,
10369 .flags = InputLightClass::BRIGHTNESS,
10370 .path = ""};
10371 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010372
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010373 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010374 InputDeviceInfo info;
10375 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010376 std::vector<InputDeviceLightInfo> lights = info.getLights();
10377 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010378 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10379 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10380
10381 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_BRIGHTNESS));
10382 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_BRIGHTNESS);
10383}
10384
DingYong99f2c3c2023-12-20 15:46:06 +080010385TEST_F(LightControllerTest, MonoKeyboardMuteLight) {
10386 RawLightInfo infoMono = {.id = 1,
10387 .name = "mono_keyboard_mute",
10388 .maxBrightness = 255,
10389 .flags = InputLightClass::BRIGHTNESS |
10390 InputLightClass::KEYBOARD_MIC_MUTE,
10391 .path = ""};
10392 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10393
10394 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10395 std::list<NotifyArgs> unused =
10396 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10397 /*changes=*/{});
10398
10399 InputDeviceInfo info;
10400 controller.populateDeviceInfo(&info);
10401 std::vector<InputDeviceLightInfo> lights = info.getLights();
10402 ASSERT_EQ(1U, lights.size());
10403 ASSERT_EQ(InputDeviceLightType::KEYBOARD_MIC_MUTE, lights[0].type);
10404 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10405}
10406
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010407TEST_F(LightControllerTest, MonoKeyboardBacklight) {
10408 RawLightInfo infoMono = {.id = 1,
10409 .name = "mono_keyboard_backlight",
10410 .maxBrightness = 255,
10411 .flags = InputLightClass::BRIGHTNESS |
10412 InputLightClass::KEYBOARD_BACKLIGHT,
10413 .path = ""};
10414 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10415
10416 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10417 InputDeviceInfo info;
10418 controller.populateDeviceInfo(&info);
10419 std::vector<InputDeviceLightInfo> lights = info.getLights();
10420 ASSERT_EQ(1U, lights.size());
10421 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10422 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010423
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010424 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_BRIGHTNESS));
10425 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_BRIGHTNESS);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010426}
10427
Vaibhav Devmurari16c24192023-05-04 15:20:12 +000010428TEST_F(LightControllerTest, Ignore_MonoLight_WithPreferredBacklightLevels) {
10429 RawLightInfo infoMono = {.id = 1,
10430 .name = "mono_light",
10431 .maxBrightness = 255,
10432 .flags = InputLightClass::BRIGHTNESS,
10433 .path = ""};
10434 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10435 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10436 "0,100,200");
10437
10438 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10439 std::list<NotifyArgs> unused =
10440 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10441 /*changes=*/{});
10442
10443 InputDeviceInfo info;
10444 controller.populateDeviceInfo(&info);
10445 std::vector<InputDeviceLightInfo> lights = info.getLights();
10446 ASSERT_EQ(1U, lights.size());
10447 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10448}
10449
10450TEST_F(LightControllerTest, KeyboardBacklight_WithNoPreferredBacklightLevels) {
10451 RawLightInfo infoMono = {.id = 1,
10452 .name = "mono_keyboard_backlight",
10453 .maxBrightness = 255,
10454 .flags = InputLightClass::BRIGHTNESS |
10455 InputLightClass::KEYBOARD_BACKLIGHT,
10456 .path = ""};
10457 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10458
10459 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10460 std::list<NotifyArgs> unused =
10461 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10462 /*changes=*/{});
10463
10464 InputDeviceInfo info;
10465 controller.populateDeviceInfo(&info);
10466 std::vector<InputDeviceLightInfo> lights = info.getLights();
10467 ASSERT_EQ(1U, lights.size());
10468 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10469}
10470
10471TEST_F(LightControllerTest, KeyboardBacklight_WithPreferredBacklightLevels) {
10472 RawLightInfo infoMono = {.id = 1,
10473 .name = "mono_keyboard_backlight",
10474 .maxBrightness = 255,
10475 .flags = InputLightClass::BRIGHTNESS |
10476 InputLightClass::KEYBOARD_BACKLIGHT,
10477 .path = ""};
10478 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10479 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10480 "0,100,200");
10481
10482 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10483 std::list<NotifyArgs> unused =
10484 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10485 /*changes=*/{});
10486
10487 InputDeviceInfo info;
10488 controller.populateDeviceInfo(&info);
10489 std::vector<InputDeviceLightInfo> lights = info.getLights();
10490 ASSERT_EQ(1U, lights.size());
10491 ASSERT_EQ(3U, lights[0].preferredBrightnessLevels.size());
10492 std::set<BrightnessLevel>::iterator it = lights[0].preferredBrightnessLevels.begin();
10493 ASSERT_EQ(BrightnessLevel(0), *it);
10494 std::advance(it, 1);
10495 ASSERT_EQ(BrightnessLevel(100), *it);
10496 std::advance(it, 1);
10497 ASSERT_EQ(BrightnessLevel(200), *it);
10498}
10499
10500TEST_F(LightControllerTest, KeyboardBacklight_WithWrongPreferredBacklightLevels) {
10501 RawLightInfo infoMono = {.id = 1,
10502 .name = "mono_keyboard_backlight",
10503 .maxBrightness = 255,
10504 .flags = InputLightClass::BRIGHTNESS |
10505 InputLightClass::KEYBOARD_BACKLIGHT,
10506 .path = ""};
10507 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10508 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10509 "0,100,200,300,400,500");
10510
10511 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10512 std::list<NotifyArgs> unused =
10513 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10514 /*changes=*/{});
10515
10516 InputDeviceInfo info;
10517 controller.populateDeviceInfo(&info);
10518 std::vector<InputDeviceLightInfo> lights = info.getLights();
10519 ASSERT_EQ(1U, lights.size());
10520 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10521}
10522
Chris Yee2b1e5c2021-03-10 22:45:12 -080010523TEST_F(LightControllerTest, RGBLight) {
10524 RawLightInfo infoRed = {.id = 1,
10525 .name = "red",
10526 .maxBrightness = 255,
10527 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED,
10528 .path = ""};
10529 RawLightInfo infoGreen = {.id = 2,
10530 .name = "green",
10531 .maxBrightness = 255,
10532 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN,
10533 .path = ""};
10534 RawLightInfo infoBlue = {.id = 3,
10535 .name = "blue",
10536 .maxBrightness = 255,
10537 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE,
10538 .path = ""};
10539 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10540 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10541 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10542
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010543 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010544 InputDeviceInfo info;
10545 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010546 std::vector<InputDeviceLightInfo> lights = info.getLights();
10547 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010548 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10549 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10550 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10551
10552 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10553 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10554}
10555
10556TEST_F(LightControllerTest, CorrectRGBKeyboardBacklight) {
10557 RawLightInfo infoRed = {.id = 1,
10558 .name = "red_keyboard_backlight",
10559 .maxBrightness = 255,
10560 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED |
10561 InputLightClass::KEYBOARD_BACKLIGHT,
10562 .path = ""};
10563 RawLightInfo infoGreen = {.id = 2,
10564 .name = "green_keyboard_backlight",
10565 .maxBrightness = 255,
10566 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN |
10567 InputLightClass::KEYBOARD_BACKLIGHT,
10568 .path = ""};
10569 RawLightInfo infoBlue = {.id = 3,
10570 .name = "blue_keyboard_backlight",
10571 .maxBrightness = 255,
10572 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE |
10573 InputLightClass::KEYBOARD_BACKLIGHT,
10574 .path = ""};
10575 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10576 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10577 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10578
10579 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10580 InputDeviceInfo info;
10581 controller.populateDeviceInfo(&info);
10582 std::vector<InputDeviceLightInfo> lights = info.getLights();
10583 ASSERT_EQ(1U, lights.size());
10584 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10585 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10586 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10587
10588 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10589 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10590}
10591
10592TEST_F(LightControllerTest, IncorrectRGBKeyboardBacklight) {
10593 RawLightInfo infoRed = {.id = 1,
10594 .name = "red",
10595 .maxBrightness = 255,
10596 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED,
10597 .path = ""};
10598 RawLightInfo infoGreen = {.id = 2,
10599 .name = "green",
10600 .maxBrightness = 255,
10601 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN,
10602 .path = ""};
10603 RawLightInfo infoBlue = {.id = 3,
10604 .name = "blue",
10605 .maxBrightness = 255,
10606 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE,
10607 .path = ""};
10608 RawLightInfo infoGlobal = {.id = 3,
10609 .name = "global_keyboard_backlight",
10610 .maxBrightness = 255,
10611 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GLOBAL |
10612 InputLightClass::KEYBOARD_BACKLIGHT,
10613 .path = ""};
10614 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10615 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10616 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10617 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoGlobal));
10618
10619 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10620 InputDeviceInfo info;
10621 controller.populateDeviceInfo(&info);
10622 std::vector<InputDeviceLightInfo> lights = info.getLights();
10623 ASSERT_EQ(1U, lights.size());
10624 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10625 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10626 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010627
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010628 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10629 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010630}
10631
10632TEST_F(LightControllerTest, MultiColorRGBLight) {
10633 RawLightInfo infoColor = {.id = 1,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010634 .name = "multi_color",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010635 .maxBrightness = 255,
10636 .flags = InputLightClass::BRIGHTNESS |
10637 InputLightClass::MULTI_INTENSITY |
10638 InputLightClass::MULTI_INDEX,
10639 .path = ""};
10640
10641 mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
10642
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010643 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010644 InputDeviceInfo info;
10645 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010646 std::vector<InputDeviceLightInfo> lights = info.getLights();
10647 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010648 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10649 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10650 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10651
10652 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10653 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10654}
10655
10656TEST_F(LightControllerTest, MultiColorRGBKeyboardBacklight) {
10657 RawLightInfo infoColor = {.id = 1,
10658 .name = "multi_color_keyboard_backlight",
10659 .maxBrightness = 255,
10660 .flags = InputLightClass::BRIGHTNESS |
10661 InputLightClass::MULTI_INTENSITY |
10662 InputLightClass::MULTI_INDEX |
10663 InputLightClass::KEYBOARD_BACKLIGHT,
10664 .path = ""};
10665
10666 mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
10667
10668 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10669 InputDeviceInfo info;
10670 controller.populateDeviceInfo(&info);
10671 std::vector<InputDeviceLightInfo> lights = info.getLights();
10672 ASSERT_EQ(1U, lights.size());
10673 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10674 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10675 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010676
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010677 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10678 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010679}
10680
Josep del Rioa1046a82023-08-24 19:57:27 +000010681TEST_F(LightControllerTest, SonyPlayerIdLight) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010682 RawLightInfo info1 = {.id = 1,
Josep del Rioa1046a82023-08-24 19:57:27 +000010683 .name = "sony1",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010684 .maxBrightness = 255,
10685 .flags = InputLightClass::BRIGHTNESS,
10686 .path = ""};
10687 RawLightInfo info2 = {.id = 2,
Josep del Rioa1046a82023-08-24 19:57:27 +000010688 .name = "sony2",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010689 .maxBrightness = 255,
10690 .flags = InputLightClass::BRIGHTNESS,
10691 .path = ""};
10692 RawLightInfo info3 = {.id = 3,
Josep del Rioa1046a82023-08-24 19:57:27 +000010693 .name = "sony3",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010694 .maxBrightness = 255,
10695 .flags = InputLightClass::BRIGHTNESS,
10696 .path = ""};
10697 RawLightInfo info4 = {.id = 4,
Josep del Rioa1046a82023-08-24 19:57:27 +000010698 .name = "sony4",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010699 .maxBrightness = 255,
10700 .flags = InputLightClass::BRIGHTNESS,
10701 .path = ""};
10702 mFakeEventHub->addRawLightInfo(info1.id, std::move(info1));
10703 mFakeEventHub->addRawLightInfo(info2.id, std::move(info2));
10704 mFakeEventHub->addRawLightInfo(info3.id, std::move(info3));
10705 mFakeEventHub->addRawLightInfo(info4.id, std::move(info4));
10706
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010707 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010708 InputDeviceInfo info;
10709 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010710 std::vector<InputDeviceLightInfo> lights = info.getLights();
10711 ASSERT_EQ(1U, lights.size());
Josep del Rioa1046a82023-08-24 19:57:27 +000010712 ASSERT_STREQ("sony", lights[0].name.c_str());
10713 ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
10714 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10715 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10716
10717 ASSERT_FALSE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10718 ASSERT_TRUE(controller.setLightPlayerId(lights[0].id, LIGHT_PLAYER_ID));
10719 ASSERT_EQ(controller.getLightPlayerId(lights[0].id).value_or(-1), LIGHT_PLAYER_ID);
10720 ASSERT_STREQ("sony", lights[0].name.c_str());
10721}
10722
10723TEST_F(LightControllerTest, PlayerIdLight) {
10724 RawLightInfo info1 = {.id = 1,
10725 .name = "player-1",
10726 .maxBrightness = 255,
10727 .flags = InputLightClass::BRIGHTNESS,
10728 .path = ""};
10729 RawLightInfo info2 = {.id = 2,
10730 .name = "player-2",
10731 .maxBrightness = 255,
10732 .flags = InputLightClass::BRIGHTNESS,
10733 .path = ""};
10734 RawLightInfo info3 = {.id = 3,
10735 .name = "player-3",
10736 .maxBrightness = 255,
10737 .flags = InputLightClass::BRIGHTNESS,
10738 .path = ""};
10739 RawLightInfo info4 = {.id = 4,
10740 .name = "player-4",
10741 .maxBrightness = 255,
10742 .flags = InputLightClass::BRIGHTNESS,
10743 .path = ""};
10744 mFakeEventHub->addRawLightInfo(info1.id, std::move(info1));
10745 mFakeEventHub->addRawLightInfo(info2.id, std::move(info2));
10746 mFakeEventHub->addRawLightInfo(info3.id, std::move(info3));
10747 mFakeEventHub->addRawLightInfo(info4.id, std::move(info4));
10748
10749 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10750 InputDeviceInfo info;
10751 controller.populateDeviceInfo(&info);
10752 std::vector<InputDeviceLightInfo> lights = info.getLights();
10753 ASSERT_EQ(1U, lights.size());
10754 ASSERT_STREQ("player", lights[0].name.c_str());
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010755 ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010756 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10757 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010758
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010759 ASSERT_FALSE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10760 ASSERT_TRUE(controller.setLightPlayerId(lights[0].id, LIGHT_PLAYER_ID));
10761 ASSERT_EQ(controller.getLightPlayerId(lights[0].id).value_or(-1), LIGHT_PLAYER_ID);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010762}
10763
Michael Wrightd02c5b62014-02-10 15:10:22 -080010764} // namespace android