blob: 2d50c37830b68957e563c2fcbad599b48d2f0a46 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Dominik Laskowski2f01d772022-03-23 16:01:29 -070017#include <cinttypes>
18#include <memory>
Harry Cuttsf13161a2023-03-08 14:15:49 +000019#include <optional>
Dominik Laskowski2f01d772022-03-23 16:01:29 -070020
Prabir Pradhan2770d242019-09-02 18:07:11 -070021#include <CursorInputMapper.h>
22#include <InputDevice.h>
23#include <InputMapper.h>
24#include <InputReader.h>
Prabir Pradhan1aed8582019-12-30 11:46:51 -080025#include <InputReaderBase.h>
26#include <InputReaderFactory.h>
Arthur Hung6d5b4b22022-01-21 07:21:10 +000027#include <JoystickInputMapper.h>
Prabir Pradhan2770d242019-09-02 18:07:11 -070028#include <KeyboardInputMapper.h>
29#include <MultiTouchInputMapper.h>
Prabir Pradhan018faea2024-05-08 21:52:54 +000030#include <NotifyArgsBuilders.h>
Chris Ye1dd2e5c2021-04-04 23:12:41 -070031#include <PeripheralController.h>
Chris Yef59a2f42020-10-16 12:55:26 -070032#include <SensorInputMapper.h>
Prabir Pradhan2770d242019-09-02 18:07:11 -070033#include <SingleTouchInputMapper.h>
34#include <SwitchInputMapper.h>
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000035#include <TestEventMatchers.h>
Prabir Pradhan2770d242019-09-02 18:07:11 -070036#include <TestInputListener.h>
37#include <TouchInputMapper.h>
Prabir Pradhan1aed8582019-12-30 11:46:51 -080038#include <UinputDevice.h>
Chris Ye87143712020-11-10 05:05:58 +000039#include <VibratorInputMapper.h>
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070040#include <android-base/thread_annotations.h>
Byoungho Jungda10dd32023-10-06 17:03:45 +090041#include <com_android_input_flags.h>
Michael Wrighta9cf4192022-12-01 23:46:39 +000042#include <ftl/enum.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080043#include <gtest/gtest.h>
Michael Wrighta9cf4192022-12-01 23:46:39 +000044#include <ui/Rotation.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080045
Siarhei Vishniakou21e96e62022-10-27 10:23:37 -070046#include <thread>
Harry Cuttsa5b71292022-11-28 12:56:17 +000047#include "FakeEventHub.h"
Harry Cutts6b5fbc52022-11-28 16:37:43 +000048#include "FakeInputReaderPolicy.h"
Harry Cuttse6512e12022-11-28 18:44:01 +000049#include "InputMapperTest.h"
Harry Cutts144ff542022-11-28 17:41:06 +000050#include "InstrumentedInputReader.h"
Harry Cuttsa5b71292022-11-28 12:56:17 +000051#include "TestConstants.h"
Michael Wrightdde67b82020-10-27 16:09:22 +000052#include "input/DisplayViewport.h"
53#include "input/Input.h"
Michael Wright17db18e2020-06-26 20:51:44 +010054
Michael Wrightd02c5b62014-02-10 15:10:22 -080055namespace android {
56
Dominik Laskowski2f01d772022-03-23 16:01:29 -070057using namespace ftl::flag_operators;
Prabir Pradhan739dca42022-09-09 20:12:01 +000058using testing::AllOf;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070059using std::chrono_literals::operator""ms;
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -080060using std::chrono_literals::operator""s;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070061
Michael Wrightd02c5b62014-02-10 15:10:22 -080062// Arbitrary display properties.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070063static constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhanc13ff082022-09-08 22:03:30 +000064static const std::string DISPLAY_UNIQUE_ID = "local:1";
Linnan Li13bf76a2024-05-05 19:18:02 +080065static constexpr ui::LogicalDisplayId SECONDARY_DISPLAY_ID =
66 ui::LogicalDisplayId{DISPLAY_ID.val() + 1};
arthurhungcc7f9802020-04-30 17:55:40 +080067static constexpr int32_t DISPLAY_WIDTH = 480;
68static constexpr int32_t DISPLAY_HEIGHT = 800;
Linnan Li13bf76a2024-05-05 19:18:02 +080069static constexpr ui::LogicalDisplayId VIRTUAL_DISPLAY_ID = ui::LogicalDisplayId{1};
arthurhungcc7f9802020-04-30 17:55:40 +080070static constexpr int32_t VIRTUAL_DISPLAY_WIDTH = 400;
71static constexpr int32_t VIRTUAL_DISPLAY_HEIGHT = 500;
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -070072static const char* VIRTUAL_DISPLAY_UNIQUE_ID = "virtual:1";
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -070073static constexpr std::optional<uint8_t> NO_PORT = std::nullopt; // no physical port is specified
Michael Wrightd02c5b62014-02-10 15:10:22 -080074
arthurhungcc7f9802020-04-30 17:55:40 +080075static constexpr int32_t FIRST_SLOT = 0;
76static constexpr int32_t SECOND_SLOT = 1;
77static constexpr int32_t THIRD_SLOT = 2;
78static constexpr int32_t INVALID_TRACKING_ID = -1;
79static constexpr int32_t FIRST_TRACKING_ID = 0;
80static constexpr int32_t SECOND_TRACKING_ID = 1;
81static constexpr int32_t THIRD_TRACKING_ID = 2;
Chris Ye3fdbfef2021-01-06 18:45:18 -080082static constexpr int32_t LIGHT_BRIGHTNESS = 0x55000000;
83static constexpr int32_t LIGHT_COLOR = 0x7F448866;
84static constexpr int32_t LIGHT_PLAYER_ID = 2;
arthurhungcc7f9802020-04-30 17:55:40 +080085
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -080086static constexpr int32_t ACTION_POINTER_0_DOWN =
87 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
88static constexpr int32_t ACTION_POINTER_0_UP =
89 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
90static constexpr int32_t ACTION_POINTER_1_DOWN =
91 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
92static constexpr int32_t ACTION_POINTER_1_UP =
93 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
94
Prabir Pradhanb08a0e82023-09-14 22:28:32 +000095static constexpr uint32_t STYLUS_FUSION_SOURCE =
96 AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_BLUETOOTH_STYLUS;
97
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +000098// Minimum timestamp separation between subsequent input events from a Bluetooth device.
99static constexpr nsecs_t MIN_BLUETOOTH_TIMESTAMP_DELTA = ms2ns(4);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +0000100
Byoungho Jungda10dd32023-10-06 17:03:45 +0900101namespace input_flags = com::android::input::flags;
102
Michael Wrightd02c5b62014-02-10 15:10:22 -0800103template<typename T>
104static inline T min(T a, T b) {
105 return a < b ? a : b;
106}
107
108static inline float avg(float x, float y) {
109 return (x + y) / 2;
110}
111
Chris Ye3fdbfef2021-01-06 18:45:18 -0800112// Mapping for light color name and the light color
113const std::unordered_map<std::string, LightColor> LIGHT_COLORS = {{"red", LightColor::RED},
114 {"green", LightColor::GREEN},
115 {"blue", LightColor::BLUE}};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800116
Michael Wrighta9cf4192022-12-01 23:46:39 +0000117static ui::Rotation getInverseRotation(ui::Rotation orientation) {
Prabir Pradhanc14266f2021-05-12 15:56:24 -0700118 switch (orientation) {
Michael Wrighta9cf4192022-12-01 23:46:39 +0000119 case ui::ROTATION_90:
120 return ui::ROTATION_270;
121 case ui::ROTATION_270:
122 return ui::ROTATION_90;
Prabir Pradhanc14266f2021-05-12 15:56:24 -0700123 default:
124 return orientation;
125 }
126}
127
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800128static void assertAxisResolution(MultiTouchInputMapper& mapper, int axis, float resolution) {
129 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +0000130 mapper.populateDeviceInfo(info);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800131
132 const InputDeviceInfo::MotionRange* motionRange =
133 info.getMotionRange(axis, AINPUT_SOURCE_TOUCHSCREEN);
134 ASSERT_NEAR(motionRange->resolution, resolution, EPSILON);
135}
136
137static void assertAxisNotPresent(MultiTouchInputMapper& mapper, int axis) {
138 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +0000139 mapper.populateDeviceInfo(info);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800140
141 const InputDeviceInfo::MotionRange* motionRange =
142 info.getMotionRange(axis, AINPUT_SOURCE_TOUCHSCREEN);
143 ASSERT_EQ(nullptr, motionRange);
144}
145
Siarhei Vishniakou21e96e62022-10-27 10:23:37 -0700146[[maybe_unused]] static void dumpReader(InputReader& reader) {
147 std::string dump;
148 reader.dump(dump);
149 std::istringstream iss(dump);
150 for (std::string line; std::getline(iss, line);) {
151 ALOGE("%s", line.c_str());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -0800152 std::this_thread::sleep_for(1ms);
Siarhei Vishniakou21e96e62022-10-27 10:23:37 -0700153 }
154}
155
Michael Wrightd02c5b62014-02-10 15:10:22 -0800156// --- FakeInputMapper ---
157
158class FakeInputMapper : public InputMapper {
159 uint32_t mSources;
160 int32_t mKeyboardType;
161 int32_t mMetaState;
162 KeyedVector<int32_t, int32_t> mKeyCodeStates;
163 KeyedVector<int32_t, int32_t> mScanCodeStates;
164 KeyedVector<int32_t, int32_t> mSwitchStates;
Philip Junker4af3b3d2021-12-14 10:36:55 +0100165 // fake mapping which would normally come from keyCharacterMap
166 std::unordered_map<int32_t, int32_t> mKeyCodeMapping;
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800167 std::vector<int32_t> mSupportedKeyCodes;
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700168 std::list<NotifyArgs> mProcessResult;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800169
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700170 std::mutex mLock;
171 std::condition_variable mStateChangedCondition;
172 bool mConfigureWasCalled GUARDED_BY(mLock);
173 bool mResetWasCalled GUARDED_BY(mLock);
174 bool mProcessWasCalled GUARDED_BY(mLock);
175 RawEvent mLastEvent GUARDED_BY(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800176
Arthur Hungc23540e2018-11-29 20:42:11 +0800177 std::optional<DisplayViewport> mViewport;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800178public:
Arpit Singh8e6fb252023-04-06 11:49:17 +0000179 FakeInputMapper(InputDeviceContext& deviceContext, const InputReaderConfiguration& readerConfig,
180 uint32_t sources)
181 : InputMapper(deviceContext, readerConfig),
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800182 mSources(sources),
183 mKeyboardType(AINPUT_KEYBOARD_TYPE_NONE),
Michael Wrightd02c5b62014-02-10 15:10:22 -0800184 mMetaState(0),
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800185 mConfigureWasCalled(false),
186 mResetWasCalled(false),
187 mProcessWasCalled(false) {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800188
Chris Yea52ade12020-08-27 16:49:20 -0700189 virtual ~FakeInputMapper() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800190
191 void setKeyboardType(int32_t keyboardType) {
192 mKeyboardType = keyboardType;
193 }
194
195 void setMetaState(int32_t metaState) {
196 mMetaState = metaState;
197 }
198
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700199 // Sets the return value for the `process` call.
200 void setProcessResult(std::list<NotifyArgs> notifyArgs) {
201 mProcessResult.clear();
202 for (auto notifyArg : notifyArgs) {
203 mProcessResult.push_back(notifyArg);
204 }
205 }
206
Michael Wrightd02c5b62014-02-10 15:10:22 -0800207 void assertConfigureWasCalled() {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700208 std::unique_lock<std::mutex> lock(mLock);
209 base::ScopedLockAssertion assumeLocked(mLock);
210 const bool configureCalled =
211 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
212 return mConfigureWasCalled;
213 });
214 if (!configureCalled) {
215 FAIL() << "Expected configure() to have been called.";
216 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800217 mConfigureWasCalled = false;
218 }
219
220 void assertResetWasCalled() {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700221 std::unique_lock<std::mutex> lock(mLock);
222 base::ScopedLockAssertion assumeLocked(mLock);
223 const bool resetCalled =
224 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
225 return mResetWasCalled;
226 });
227 if (!resetCalled) {
228 FAIL() << "Expected reset() to have been called.";
229 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800230 mResetWasCalled = false;
231 }
232
Prabir Pradhanf8d9e442023-12-06 22:06:13 +0000233 void assertResetWasNotCalled() {
234 std::scoped_lock lock(mLock);
235 ASSERT_FALSE(mResetWasCalled) << "Expected reset to not have been called.";
236 }
237
Yi Kong9b14ac62018-07-17 13:48:38 -0700238 void assertProcessWasCalled(RawEvent* outLastEvent = nullptr) {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700239 std::unique_lock<std::mutex> lock(mLock);
240 base::ScopedLockAssertion assumeLocked(mLock);
241 const bool processCalled =
242 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
243 return mProcessWasCalled;
244 });
245 if (!processCalled) {
246 FAIL() << "Expected process() to have been called.";
247 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800248 if (outLastEvent) {
249 *outLastEvent = mLastEvent;
250 }
251 mProcessWasCalled = false;
252 }
253
Prabir Pradhanf8d9e442023-12-06 22:06:13 +0000254 void assertProcessWasNotCalled() {
255 std::scoped_lock lock(mLock);
256 ASSERT_FALSE(mProcessWasCalled) << "Expected process to not have been called.";
257 }
258
Michael Wrightd02c5b62014-02-10 15:10:22 -0800259 void setKeyCodeState(int32_t keyCode, int32_t state) {
260 mKeyCodeStates.replaceValueFor(keyCode, state);
261 }
262
263 void setScanCodeState(int32_t scanCode, int32_t state) {
264 mScanCodeStates.replaceValueFor(scanCode, state);
265 }
266
267 void setSwitchState(int32_t switchCode, int32_t state) {
268 mSwitchStates.replaceValueFor(switchCode, state);
269 }
270
271 void addSupportedKeyCode(int32_t keyCode) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800272 mSupportedKeyCodes.push_back(keyCode);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800273 }
274
Philip Junker4af3b3d2021-12-14 10:36:55 +0100275 void addKeyCodeMapping(int32_t fromKeyCode, int32_t toKeyCode) {
276 mKeyCodeMapping.insert_or_assign(fromKeyCode, toKeyCode);
277 }
278
Michael Wrightd02c5b62014-02-10 15:10:22 -0800279private:
Philip Junker4af3b3d2021-12-14 10:36:55 +0100280 uint32_t getSources() const override { return mSources; }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800281
Harry Cuttsd02ea102023-03-17 18:21:30 +0000282 void populateDeviceInfo(InputDeviceInfo& deviceInfo) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800283 InputMapper::populateDeviceInfo(deviceInfo);
284
285 if (mKeyboardType != AINPUT_KEYBOARD_TYPE_NONE) {
Harry Cuttsd02ea102023-03-17 18:21:30 +0000286 deviceInfo.setKeyboardType(mKeyboardType);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800287 }
288 }
289
Arpit Singhed6c3de2023-04-05 19:24:37 +0000290 std::list<NotifyArgs> reconfigure(nsecs_t, const InputReaderConfiguration& config,
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000291 ConfigurationChanges changes) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700292 std::scoped_lock<std::mutex> lock(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800293 mConfigureWasCalled = true;
Arthur Hungc23540e2018-11-29 20:42:11 +0800294
295 // Find the associated viewport if exist.
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800296 const std::optional<uint8_t> displayPort = getDeviceContext().getAssociatedDisplayPort();
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000297 if (displayPort && changes.test(InputReaderConfiguration::Change::DISPLAY_INFO)) {
Arpit Singhed6c3de2023-04-05 19:24:37 +0000298 mViewport = config.getDisplayViewportByPort(*displayPort);
Arthur Hungc23540e2018-11-29 20:42:11 +0800299 }
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700300
301 mStateChangedCondition.notify_all();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700302 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800303 }
304
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700305 std::list<NotifyArgs> reset(nsecs_t) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700306 std::scoped_lock<std::mutex> lock(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800307 mResetWasCalled = true;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700308 mStateChangedCondition.notify_all();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700309 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800310 }
311
Harry Cuttsa32a1192024-06-04 15:10:31 +0000312 std::list<NotifyArgs> process(const RawEvent& rawEvent) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700313 std::scoped_lock<std::mutex> lock(mLock);
Harry Cuttsa32a1192024-06-04 15:10:31 +0000314 mLastEvent = rawEvent;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800315 mProcessWasCalled = true;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700316 mStateChangedCondition.notify_all();
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700317 return mProcessResult;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800318 }
319
Chris Yea52ade12020-08-27 16:49:20 -0700320 int32_t getKeyCodeState(uint32_t, int32_t keyCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800321 ssize_t index = mKeyCodeStates.indexOfKey(keyCode);
322 return index >= 0 ? mKeyCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
323 }
324
Philip Junker4af3b3d2021-12-14 10:36:55 +0100325 int32_t getKeyCodeForKeyLocation(int32_t locationKeyCode) const override {
326 auto it = mKeyCodeMapping.find(locationKeyCode);
327 return it != mKeyCodeMapping.end() ? it->second : locationKeyCode;
328 }
329
Chris Yea52ade12020-08-27 16:49:20 -0700330 int32_t getScanCodeState(uint32_t, int32_t scanCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800331 ssize_t index = mScanCodeStates.indexOfKey(scanCode);
332 return index >= 0 ? mScanCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
333 }
334
Chris Yea52ade12020-08-27 16:49:20 -0700335 int32_t getSwitchState(uint32_t, int32_t switchCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800336 ssize_t index = mSwitchStates.indexOfKey(switchCode);
337 return index >= 0 ? mSwitchStates.valueAt(index) : AKEY_STATE_UNKNOWN;
338 }
339
Chris Yea52ade12020-08-27 16:49:20 -0700340 // Return true if the device has non-empty key layout.
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700341 bool markSupportedKeyCodes(uint32_t, const std::vector<int32_t>& keyCodes,
Chris Yea52ade12020-08-27 16:49:20 -0700342 uint8_t* outFlags) override {
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700343 for (size_t i = 0; i < keyCodes.size(); i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800344 for (size_t j = 0; j < mSupportedKeyCodes.size(); j++) {
345 if (keyCodes[i] == mSupportedKeyCodes[j]) {
346 outFlags[i] = 1;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800347 }
348 }
349 }
Chris Yea52ade12020-08-27 16:49:20 -0700350 bool result = mSupportedKeyCodes.size() > 0;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800351 return result;
352 }
353
354 virtual int32_t getMetaState() {
355 return mMetaState;
356 }
357
358 virtual void fadePointer() {
359 }
Arthur Hungc23540e2018-11-29 20:42:11 +0800360
Linnan Li13bf76a2024-05-05 19:18:02 +0800361 virtual std::optional<ui::LogicalDisplayId> getAssociatedDisplay() {
Arthur Hungc23540e2018-11-29 20:42:11 +0800362 if (mViewport) {
363 return std::make_optional(mViewport->displayId);
364 }
365 return std::nullopt;
366 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800367};
368
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700369// --- InputReaderPolicyTest ---
370class InputReaderPolicyTest : public testing::Test {
Siarhei Vishniakoucd7ac1e2018-10-15 13:39:50 -0700371protected:
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700372 sp<FakeInputReaderPolicy> mFakePolicy;
373
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700374 void SetUp() override { mFakePolicy = sp<FakeInputReaderPolicy>::make(); }
Chris Yea52ade12020-08-27 16:49:20 -0700375 void TearDown() override { mFakePolicy.clear(); }
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700376};
377
378/**
379 * Check that empty set of viewports is an acceptable configuration.
380 * Also try to get internal viewport two different ways - by type and by uniqueId.
381 *
382 * There will be confusion if two viewports with empty uniqueId and identical type are present.
383 * Such configuration is not currently allowed.
384 */
385TEST_F(InputReaderPolicyTest, Viewports_GetCleared) {
Siarhei Vishniakoucd7ac1e2018-10-15 13:39:50 -0700386 static const std::string uniqueId = "local:0";
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700387
388 // We didn't add any viewports yet, so there shouldn't be any.
389 std::optional<DisplayViewport> internalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100390 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700391 ASSERT_FALSE(internalViewport);
392
393 // Add an internal viewport, then clear it
Michael Wrighta9cf4192022-12-01 23:46:39 +0000394 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000395 /*isActive=*/true, uniqueId, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700396
397 // Check matching by uniqueId
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700398 internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700399 ASSERT_TRUE(internalViewport);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100400 ASSERT_EQ(ViewportType::INTERNAL, internalViewport->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700401
402 // Check matching by viewport type
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100403 internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700404 ASSERT_TRUE(internalViewport);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700405 ASSERT_EQ(uniqueId, internalViewport->uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700406
407 mFakePolicy->clearViewports();
408 // Make sure nothing is found after clear
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700409 internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700410 ASSERT_FALSE(internalViewport);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100411 internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700412 ASSERT_FALSE(internalViewport);
413}
414
415TEST_F(InputReaderPolicyTest, Viewports_GetByType) {
416 const std::string internalUniqueId = "local:0";
417 const std::string externalUniqueId = "local:1";
418 const std::string virtualUniqueId1 = "virtual:2";
419 const std::string virtualUniqueId2 = "virtual:3";
Linnan Li13bf76a2024-05-05 19:18:02 +0800420 constexpr ui::LogicalDisplayId virtualDisplayId1 = ui::LogicalDisplayId{2};
421 constexpr ui::LogicalDisplayId virtualDisplayId2 = ui::LogicalDisplayId{3};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700422
423 // Add an internal viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000424 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000425 /*isActive=*/true, internalUniqueId, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000426 ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700427 // Add an external viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000428 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000429 /*isActive=*/true, externalUniqueId, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000430 ViewportType::EXTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700431 // Add an virtual viewport
432 mFakePolicy->addDisplayViewport(virtualDisplayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000433 ui::ROTATION_0, /*isActive=*/true, virtualUniqueId1, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000434 ViewportType::VIRTUAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700435 // Add another virtual viewport
436 mFakePolicy->addDisplayViewport(virtualDisplayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000437 ui::ROTATION_0, /*isActive=*/true, virtualUniqueId2, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000438 ViewportType::VIRTUAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700439
440 // Check matching by type for internal
441 std::optional<DisplayViewport> internalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100442 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700443 ASSERT_TRUE(internalViewport);
444 ASSERT_EQ(internalUniqueId, internalViewport->uniqueId);
445
446 // Check matching by type for external
447 std::optional<DisplayViewport> externalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100448 mFakePolicy->getDisplayViewportByType(ViewportType::EXTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700449 ASSERT_TRUE(externalViewport);
450 ASSERT_EQ(externalUniqueId, externalViewport->uniqueId);
451
452 // Check matching by uniqueId for virtual viewport #1
453 std::optional<DisplayViewport> virtualViewport1 =
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700454 mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId1);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700455 ASSERT_TRUE(virtualViewport1);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100456 ASSERT_EQ(ViewportType::VIRTUAL, virtualViewport1->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700457 ASSERT_EQ(virtualUniqueId1, virtualViewport1->uniqueId);
458 ASSERT_EQ(virtualDisplayId1, virtualViewport1->displayId);
459
460 // Check matching by uniqueId for virtual viewport #2
461 std::optional<DisplayViewport> virtualViewport2 =
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700462 mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId2);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700463 ASSERT_TRUE(virtualViewport2);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100464 ASSERT_EQ(ViewportType::VIRTUAL, virtualViewport2->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700465 ASSERT_EQ(virtualUniqueId2, virtualViewport2->uniqueId);
466 ASSERT_EQ(virtualDisplayId2, virtualViewport2->displayId);
467}
468
469
470/**
471 * We can have 2 viewports of the same kind. We can distinguish them by uniqueId, and confirm
472 * that lookup works by checking display id.
473 * Check that 2 viewports of each kind is possible, for all existing viewport types.
474 */
475TEST_F(InputReaderPolicyTest, Viewports_TwoOfSameType) {
476 const std::string uniqueId1 = "uniqueId1";
477 const std::string uniqueId2 = "uniqueId2";
Linnan Li13bf76a2024-05-05 19:18:02 +0800478 constexpr ui::LogicalDisplayId displayId1 = ui::LogicalDisplayId{2};
479 constexpr ui::LogicalDisplayId displayId2 = ui::LogicalDisplayId{3};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700480
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100481 std::vector<ViewportType> types = {ViewportType::INTERNAL, ViewportType::EXTERNAL,
482 ViewportType::VIRTUAL};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700483 for (const ViewportType& type : types) {
484 mFakePolicy->clearViewports();
485 // Add a viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000486 mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000487 /*isActive=*/true, uniqueId1, NO_PORT, type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700488 // Add another viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000489 mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000490 /*isActive=*/true, uniqueId2, NO_PORT, type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700491
492 // Check that correct display viewport was returned by comparing the display IDs.
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700493 std::optional<DisplayViewport> viewport1 =
494 mFakePolicy->getDisplayViewportByUniqueId(uniqueId1);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700495 ASSERT_TRUE(viewport1);
496 ASSERT_EQ(displayId1, viewport1->displayId);
497 ASSERT_EQ(type, viewport1->type);
498
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700499 std::optional<DisplayViewport> viewport2 =
500 mFakePolicy->getDisplayViewportByUniqueId(uniqueId2);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700501 ASSERT_TRUE(viewport2);
502 ASSERT_EQ(displayId2, viewport2->displayId);
503 ASSERT_EQ(type, viewport2->type);
504
505 // When there are multiple viewports of the same kind, and uniqueId is not specified
506 // in the call to getDisplayViewport, then that situation is not supported.
507 // The viewports can be stored in any order, so we cannot rely on the order, since that
508 // is just implementation detail.
509 // However, we can check that it still returns *a* viewport, we just cannot assert
510 // which one specifically is returned.
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700511 std::optional<DisplayViewport> someViewport = mFakePolicy->getDisplayViewportByType(type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700512 ASSERT_TRUE(someViewport);
513 }
514}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800515
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700516/**
Michael Wrightdde67b82020-10-27 16:09:22 +0000517 * When we have multiple internal displays make sure we always return the default display when
518 * querying by type.
519 */
520TEST_F(InputReaderPolicyTest, Viewports_ByTypeReturnsDefaultForInternal) {
521 const std::string uniqueId1 = "uniqueId1";
522 const std::string uniqueId2 = "uniqueId2";
Linnan Li13bf76a2024-05-05 19:18:02 +0800523 constexpr ui::LogicalDisplayId nonDefaultDisplayId = ui::LogicalDisplayId{2};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700524 ASSERT_NE(nonDefaultDisplayId, ui::LogicalDisplayId::DEFAULT)
525 << "Test display ID should not be ui::LogicalDisplayId::DEFAULT ";
Michael Wrightdde67b82020-10-27 16:09:22 +0000526
527 // Add the default display first and ensure it gets returned.
528 mFakePolicy->clearViewports();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700529 mFakePolicy->addDisplayViewport(ui::LogicalDisplayId::DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000530 ui::ROTATION_0, /*isActive=*/true, uniqueId1, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000531 ViewportType::INTERNAL);
532 mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000533 ui::ROTATION_0, /*isActive=*/true, uniqueId2, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000534 ViewportType::INTERNAL);
535
536 std::optional<DisplayViewport> viewport =
537 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
538 ASSERT_TRUE(viewport);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700539 ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, viewport->displayId);
Michael Wrightdde67b82020-10-27 16:09:22 +0000540 ASSERT_EQ(ViewportType::INTERNAL, viewport->type);
541
542 // Add the default display second to make sure order doesn't matter.
543 mFakePolicy->clearViewports();
544 mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000545 ui::ROTATION_0, /*isActive=*/true, uniqueId2, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000546 ViewportType::INTERNAL);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700547 mFakePolicy->addDisplayViewport(ui::LogicalDisplayId::DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000548 ui::ROTATION_0, /*isActive=*/true, uniqueId1, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000549 ViewportType::INTERNAL);
550
551 viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
552 ASSERT_TRUE(viewport);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700553 ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, viewport->displayId);
Michael Wrightdde67b82020-10-27 16:09:22 +0000554 ASSERT_EQ(ViewportType::INTERNAL, viewport->type);
555}
556
557/**
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700558 * Check getDisplayViewportByPort
559 */
560TEST_F(InputReaderPolicyTest, Viewports_GetByPort) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100561 constexpr ViewportType type = ViewportType::EXTERNAL;
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700562 const std::string uniqueId1 = "uniqueId1";
563 const std::string uniqueId2 = "uniqueId2";
Linnan Li13bf76a2024-05-05 19:18:02 +0800564 constexpr ui::LogicalDisplayId displayId1 = ui::LogicalDisplayId{1};
565 constexpr ui::LogicalDisplayId displayId2 = ui::LogicalDisplayId{2};
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700566 const uint8_t hdmi1 = 0;
567 const uint8_t hdmi2 = 1;
568 const uint8_t hdmi3 = 2;
569
570 mFakePolicy->clearViewports();
571 // Add a viewport that's associated with some display port that's not of interest.
Michael Wrighta9cf4192022-12-01 23:46:39 +0000572 mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000573 /*isActive=*/true, uniqueId1, hdmi3, type);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700574 // Add another viewport, connected to HDMI1 port
Michael Wrighta9cf4192022-12-01 23:46:39 +0000575 mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000576 /*isActive=*/true, uniqueId2, hdmi1, type);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700577
578 // Check that correct display viewport was returned by comparing the display ports.
579 std::optional<DisplayViewport> hdmi1Viewport = mFakePolicy->getDisplayViewportByPort(hdmi1);
580 ASSERT_TRUE(hdmi1Viewport);
581 ASSERT_EQ(displayId2, hdmi1Viewport->displayId);
582 ASSERT_EQ(uniqueId2, hdmi1Viewport->uniqueId);
583
584 // Check that we can still get the same viewport using the uniqueId
585 hdmi1Viewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId2);
586 ASSERT_TRUE(hdmi1Viewport);
587 ASSERT_EQ(displayId2, hdmi1Viewport->displayId);
588 ASSERT_EQ(uniqueId2, hdmi1Viewport->uniqueId);
589 ASSERT_EQ(type, hdmi1Viewport->type);
590
591 // Check that we cannot find a port with "HDMI2", because we never added one
592 std::optional<DisplayViewport> hdmi2Viewport = mFakePolicy->getDisplayViewportByPort(hdmi2);
593 ASSERT_FALSE(hdmi2Viewport);
594}
595
Michael Wrightd02c5b62014-02-10 15:10:22 -0800596// --- InputReaderTest ---
597
598class InputReaderTest : public testing::Test {
599protected:
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700600 std::unique_ptr<TestInputListener> mFakeListener;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800601 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou3bc7e092019-07-24 17:43:30 -0700602 std::shared_ptr<FakeEventHub> mFakeEventHub;
Prabir Pradhan28efc192019-11-05 01:10:04 +0000603 std::unique_ptr<InstrumentedInputReader> mReader;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800604
Chris Yea52ade12020-08-27 16:49:20 -0700605 void SetUp() override {
Siarhei Vishniakou3bc7e092019-07-24 17:43:30 -0700606 mFakeEventHub = std::make_unique<FakeEventHub>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700607 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700608 mFakeListener = std::make_unique<TestInputListener>();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800609
Prabir Pradhan28efc192019-11-05 01:10:04 +0000610 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700611 *mFakeListener);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800612 }
613
Chris Yea52ade12020-08-27 16:49:20 -0700614 void TearDown() override {
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700615 mFakeListener.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800616 mFakePolicy.clear();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800617 }
618
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700619 void addDevice(int32_t eventHubId, const std::string& name,
620 ftl::Flags<InputDeviceClass> classes, const PropertyMap* configuration) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800621 mFakeEventHub->addDevice(eventHubId, name, classes);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800622
623 if (configuration) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800624 mFakeEventHub->addConfigurationMap(eventHubId, configuration);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800625 }
626 mFakeEventHub->finishDeviceScan();
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000627 mReader->loopOnce();
628 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700629 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Prabir Pradhane3da4bb2023-04-05 23:51:23 +0000630 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyInputDevicesChangedWasCalled());
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700631 ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800632 }
633
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800634 void disableDevice(int32_t deviceId) {
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700635 mFakePolicy->addDisabledDevice(deviceId);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000636 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::ENABLED_STATE);
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700637 }
638
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800639 void enableDevice(int32_t deviceId) {
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700640 mFakePolicy->removeDisabledDevice(deviceId);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000641 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::ENABLED_STATE);
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700642 }
643
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800644 FakeInputMapper& addDeviceWithFakeInputMapper(int32_t deviceId, int32_t eventHubId,
Chris Ye1b0c7342020-07-28 21:57:03 -0700645 const std::string& name,
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700646 ftl::Flags<InputDeviceClass> classes,
647 uint32_t sources,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800648 const PropertyMap* configuration) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800649 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, name);
Arpit Singh8e6fb252023-04-06 11:49:17 +0000650 FakeInputMapper& mapper =
651 device->addMapper<FakeInputMapper>(eventHubId,
652 mFakePolicy->getReaderConfiguration(), sources);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -0800653 mReader->pushNextDevice(device);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800654 addDevice(eventHubId, name, classes, configuration);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800655 return mapper;
656 }
657};
658
Chris Ye98d3f532020-10-01 21:48:59 -0700659TEST_F(InputReaderTest, PolicyGetInputDevices) {
660 ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard", InputDeviceClass::KEYBOARD, nullptr));
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700661 ASSERT_NO_FATAL_FAILURE(addDevice(2, "ignored", ftl::Flags<InputDeviceClass>(0),
Chris Ye98d3f532020-10-01 21:48:59 -0700662 nullptr)); // no classes so device will be ignored
Michael Wrightd02c5b62014-02-10 15:10:22 -0800663
664 // Should also have received a notification describing the new input devices.
Chris Ye98d3f532020-10-01 21:48:59 -0700665 const std::vector<InputDeviceInfo>& inputDevices = mFakePolicy->getInputDevices();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800666 ASSERT_EQ(1U, inputDevices.size());
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800667 ASSERT_EQ(END_RESERVED_ID + 1, inputDevices[0].getId());
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100668 ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800669 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, inputDevices[0].getKeyboardType());
670 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, inputDevices[0].getSources());
Siarhei Vishniakou1983a712021-06-04 19:27:09 +0000671 ASSERT_EQ(0U, inputDevices[0].getMotionRanges().size());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800672}
673
Vaibhav Devmurari5fc7d852023-03-17 18:43:33 +0000674TEST_F(InputReaderTest, InputDeviceRecreatedOnSysfsNodeChanged) {
675 ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard", InputDeviceClass::KEYBOARD, nullptr));
676 mFakeEventHub->setSysfsRootPath(1, "xyz");
677
678 // Should also have received a notification describing the new input device.
679 ASSERT_EQ(1U, mFakePolicy->getInputDevices().size());
680 InputDeviceInfo inputDevice = mFakePolicy->getInputDevices()[0];
681 ASSERT_EQ(0U, inputDevice.getLights().size());
682
683 RawLightInfo infoMonolight = {.id = 123,
684 .name = "mono_keyboard_backlight",
685 .maxBrightness = 255,
686 .flags = InputLightClass::BRIGHTNESS,
687 .path = ""};
688 mFakeEventHub->addRawLightInfo(/*rawId=*/123, std::move(infoMonolight));
689 mReader->sysfsNodeChanged("xyz");
690 mReader->loopOnce();
691
692 // Should also have received a notification describing the new recreated input device.
693 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
694 inputDevice = mFakePolicy->getInputDevices()[0];
695 ASSERT_EQ(1U, inputDevice.getLights().size());
696}
697
Chris Yee7310032020-09-22 15:36:28 -0700698TEST_F(InputReaderTest, GetMergedInputDevices) {
699 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
700 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
701 // Add two subdevices to device
702 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
703 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000704 device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
705 AINPUT_SOURCE_KEYBOARD);
706 device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
707 AINPUT_SOURCE_KEYBOARD);
Chris Yee7310032020-09-22 15:36:28 -0700708
709 // Push same device instance for next device to be added, so they'll have same identifier.
710 mReader->pushNextDevice(device);
711 mReader->pushNextDevice(device);
712 ASSERT_NO_FATAL_FAILURE(
713 addDevice(eventHubIds[0], "fake1", InputDeviceClass::KEYBOARD, nullptr));
714 ASSERT_NO_FATAL_FAILURE(
715 addDevice(eventHubIds[1], "fake2", InputDeviceClass::KEYBOARD, nullptr));
716
717 // Two devices will be merged to one input device as they have same identifier
Siarhei Vishniakou1983a712021-06-04 19:27:09 +0000718 ASSERT_EQ(1U, mFakePolicy->getInputDevices().size());
Chris Yee7310032020-09-22 15:36:28 -0700719}
720
Chris Yee14523a2020-12-19 13:46:00 -0800721TEST_F(InputReaderTest, GetMergedInputDevicesEnabled) {
722 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
723 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
724 // Add two subdevices to device
725 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
726 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000727 device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
728 AINPUT_SOURCE_KEYBOARD);
729 device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
730 AINPUT_SOURCE_KEYBOARD);
Chris Yee14523a2020-12-19 13:46:00 -0800731
732 // Push same device instance for next device to be added, so they'll have same identifier.
733 mReader->pushNextDevice(device);
734 mReader->pushNextDevice(device);
735 // Sensor device is initially disabled
736 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1",
737 InputDeviceClass::KEYBOARD | InputDeviceClass::SENSOR,
738 nullptr));
739 // Device is disabled because the only sub device is a sensor device and disabled initially.
740 ASSERT_FALSE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
741 ASSERT_FALSE(device->isEnabled());
742 ASSERT_NO_FATAL_FAILURE(
743 addDevice(eventHubIds[1], "fake2", InputDeviceClass::KEYBOARD, nullptr));
744 // The merged device is enabled if any sub device is enabled
745 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
746 ASSERT_TRUE(device->isEnabled());
747}
748
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700749TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800750 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700751 constexpr ftl::Flags<InputDeviceClass> deviceClass(InputDeviceClass::KEYBOARD);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800752 constexpr int32_t eventHubId = 1;
753 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700754 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000755 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
756 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -0800757 mReader->pushNextDevice(device);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800758 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700759
Yi Kong9b14ac62018-07-17 13:48:38 -0700760 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(nullptr));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700761
762 NotifyDeviceResetArgs resetArgs;
763 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700764 ASSERT_EQ(deviceId, resetArgs.deviceId);
765
766 ASSERT_EQ(device->isEnabled(), true);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800767 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000768 mReader->loopOnce();
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700769
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700770 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700771 ASSERT_EQ(deviceId, resetArgs.deviceId);
772 ASSERT_EQ(device->isEnabled(), false);
773
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800774 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000775 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700776 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
777 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasNotCalled());
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700778 ASSERT_EQ(device->isEnabled(), false);
779
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800780 enableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000781 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700782 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700783 ASSERT_EQ(deviceId, resetArgs.deviceId);
784 ASSERT_EQ(device->isEnabled(), true);
785}
786
Michael Wrightd02c5b62014-02-10 15:10:22 -0800787TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800788 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700789 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800790 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800791 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800792 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800793 AINPUT_SOURCE_KEYBOARD, nullptr);
794 mapper.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800795
796 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(0,
797 AINPUT_SOURCE_ANY, AKEYCODE_A))
798 << "Should return unknown when the device id is >= 0 but unknown.";
799
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800800 ASSERT_EQ(AKEY_STATE_UNKNOWN,
801 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
802 << "Should return unknown when the device id is valid but the sources are not "
803 "supported by the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800804
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800805 ASSERT_EQ(AKEY_STATE_DOWN,
806 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
807 AKEYCODE_A))
808 << "Should return value provided by mapper when device id is valid and the device "
809 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800810
811 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(-1,
812 AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
813 << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
814
815 ASSERT_EQ(AKEY_STATE_DOWN, mReader->getKeyCodeState(-1,
816 AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
817 << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
818}
819
Philip Junker4af3b3d2021-12-14 10:36:55 +0100820TEST_F(InputReaderTest, GetKeyCodeForKeyLocation_ForwardsRequestsToMappers) {
821 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
822 constexpr int32_t eventHubId = 1;
823 FakeInputMapper& mapper = addDeviceWithFakeInputMapper(deviceId, eventHubId, "keyboard",
824 InputDeviceClass::KEYBOARD,
825 AINPUT_SOURCE_KEYBOARD, nullptr);
826 mapper.addKeyCodeMapping(AKEYCODE_Y, AKEYCODE_Z);
827
828 ASSERT_EQ(AKEYCODE_UNKNOWN, mReader->getKeyCodeForKeyLocation(0, AKEYCODE_Y))
829 << "Should return unknown when the device with the specified id is not found.";
830
831 ASSERT_EQ(AKEYCODE_Z, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_Y))
832 << "Should return correct mapping when device id is valid and mapping exists.";
833
834 ASSERT_EQ(AKEYCODE_A, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_A))
835 << "Should return the location key code when device id is valid and there's no "
836 "mapping.";
837}
838
839TEST_F(InputReaderTest, GetKeyCodeForKeyLocation_NoKeyboardMapper) {
840 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
841 constexpr int32_t eventHubId = 1;
842 FakeInputMapper& mapper = addDeviceWithFakeInputMapper(deviceId, eventHubId, "joystick",
843 InputDeviceClass::JOYSTICK,
844 AINPUT_SOURCE_GAMEPAD, nullptr);
845 mapper.addKeyCodeMapping(AKEYCODE_Y, AKEYCODE_Z);
846
847 ASSERT_EQ(AKEYCODE_UNKNOWN, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_Y))
848 << "Should return unknown when the device id is valid but there is no keyboard mapper";
849}
850
Michael Wrightd02c5b62014-02-10 15:10:22 -0800851TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800852 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700853 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800854 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800855 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800856 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800857 AINPUT_SOURCE_KEYBOARD, nullptr);
858 mapper.setScanCodeState(KEY_A, AKEY_STATE_DOWN);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800859
860 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(0,
861 AINPUT_SOURCE_ANY, KEY_A))
862 << "Should return unknown when the device id is >= 0 but unknown.";
863
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800864 ASSERT_EQ(AKEY_STATE_UNKNOWN,
865 mReader->getScanCodeState(deviceId, AINPUT_SOURCE_TRACKBALL, KEY_A))
866 << "Should return unknown when the device id is valid but the sources are not "
867 "supported by the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800868
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800869 ASSERT_EQ(AKEY_STATE_DOWN,
870 mReader->getScanCodeState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
871 KEY_A))
872 << "Should return value provided by mapper when device id is valid and the device "
873 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800874
875 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(-1,
876 AINPUT_SOURCE_TRACKBALL, KEY_A))
877 << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
878
879 ASSERT_EQ(AKEY_STATE_DOWN, mReader->getScanCodeState(-1,
880 AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, KEY_A))
881 << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
882}
883
884TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800885 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700886 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800887 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800888 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800889 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800890 AINPUT_SOURCE_KEYBOARD, nullptr);
891 mapper.setSwitchState(SW_LID, AKEY_STATE_DOWN);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800892
893 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(0,
894 AINPUT_SOURCE_ANY, SW_LID))
895 << "Should return unknown when the device id is >= 0 but unknown.";
896
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800897 ASSERT_EQ(AKEY_STATE_UNKNOWN,
898 mReader->getSwitchState(deviceId, AINPUT_SOURCE_TRACKBALL, SW_LID))
899 << "Should return unknown when the device id is valid but the sources are not "
900 "supported by the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800901
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800902 ASSERT_EQ(AKEY_STATE_DOWN,
903 mReader->getSwitchState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
904 SW_LID))
905 << "Should return value provided by mapper when device id is valid and the device "
906 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800907
908 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(-1,
909 AINPUT_SOURCE_TRACKBALL, SW_LID))
910 << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
911
912 ASSERT_EQ(AKEY_STATE_DOWN, mReader->getSwitchState(-1,
913 AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, SW_LID))
914 << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
915}
916
917TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800918 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700919 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800920 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800921 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800922 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800923 AINPUT_SOURCE_KEYBOARD, nullptr);
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100924
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800925 mapper.addSupportedKeyCode(AKEYCODE_A);
926 mapper.addSupportedKeyCode(AKEYCODE_B);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800927
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700928 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800929 uint8_t flags[4] = { 0, 0, 0, 1 };
930
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700931 ASSERT_FALSE(mReader->hasKeys(0, AINPUT_SOURCE_ANY, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800932 << "Should return false when device id is >= 0 but unknown.";
933 ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
934
935 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700936 ASSERT_FALSE(mReader->hasKeys(deviceId, AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800937 << "Should return false when device id is valid but the sources are not supported by "
938 "the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800939 ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
940
941 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700942 ASSERT_TRUE(mReader->hasKeys(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800943 keyCodes, flags))
944 << "Should return value provided by mapper when device id is valid and the device "
945 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800946 ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
947
948 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700949 ASSERT_FALSE(mReader->hasKeys(-1, AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
950 << "Should return false when the device id is < 0 but the sources are not supported by "
951 "any device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800952 ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
953
954 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700955 ASSERT_TRUE(
956 mReader->hasKeys(-1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
957 << "Should return value provided by mapper when device id is < 0 and one of the "
958 "devices supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800959 ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
960}
961
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000962TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChanged) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800963 constexpr int32_t eventHubId = 1;
Chris Ye1b0c7342020-07-28 21:57:03 -0700964 addDevice(eventHubId, "ignored", InputDeviceClass::KEYBOARD, nullptr);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800965
966 NotifyConfigurationChangedArgs args;
967
968 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(&args));
Vaibhav Devmuraric109d812024-07-10 14:21:27 +0000969 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800970 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.
Arpit Singh440bf652023-08-09 09:23:43 +00001480 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyInputDevicesChangedWasCalled());
1481 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Vaibhav Devmuraric109d812024-07-10 14:21:27 +00001482 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1483 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Arpit Singh440bf652023-08-09 09:23:43 +00001484 }
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001485};
1486
1487TEST_F(InputReaderIntegrationTest, TestInvalidDevice) {
1488 // An invalid input device that is only used for this test.
1489 class InvalidUinputDevice : public UinputDevice {
1490 public:
Harry Cutts33476232023-01-30 19:57:29 +00001491 InvalidUinputDevice() : UinputDevice("Invalid Device", /*productId=*/99) {}
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001492
1493 private:
1494 void configureDevice(int fd, uinput_user_dev* device) override {}
1495 };
1496
1497 const size_t numDevices = mFakePolicy->getInputDevices().size();
1498
1499 // UinputDevice does not set any event or key bits, so InputReader should not
1500 // consider it as a valid device.
1501 std::unique_ptr<UinputDevice> invalidDevice = createUinputDevice<InvalidUinputDevice>();
1502 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesNotChanged());
Vaibhav Devmuraric109d812024-07-10 14:21:27 +00001503 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationNotChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001504 ASSERT_EQ(numDevices, mFakePolicy->getInputDevices().size());
1505
1506 invalidDevice.reset();
1507 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesNotChanged());
Vaibhav Devmuraric109d812024-07-10 14:21:27 +00001508 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationNotChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001509 ASSERT_EQ(numDevices, mFakePolicy->getInputDevices().size());
1510}
1511
1512TEST_F(InputReaderIntegrationTest, AddNewDevice) {
1513 const size_t initialNumDevices = mFakePolicy->getInputDevices().size();
1514
1515 std::unique_ptr<UinputHomeKey> keyboard = createUinputDevice<UinputHomeKey>();
1516 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Vaibhav Devmuraric109d812024-07-10 14:21:27 +00001517 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001518 ASSERT_EQ(initialNumDevices + 1, mFakePolicy->getInputDevices().size());
1519
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001520 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001521 ASSERT_TRUE(device.has_value());
1522 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, device->getKeyboardType());
1523 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources());
1524 ASSERT_EQ(0U, device->getMotionRanges().size());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001525
1526 keyboard.reset();
1527 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Vaibhav Devmuraric109d812024-07-10 14:21:27 +00001528 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001529 ASSERT_EQ(initialNumDevices, mFakePolicy->getInputDevices().size());
1530}
1531
1532TEST_F(InputReaderIntegrationTest, SendsEventsToInputListener) {
1533 std::unique_ptr<UinputHomeKey> keyboard = createUinputDevice<UinputHomeKey>();
1534 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1535
1536 NotifyConfigurationChangedArgs configChangedArgs;
1537 ASSERT_NO_FATAL_FAILURE(
1538 mTestListener->assertNotifyConfigurationChangedWasCalled(&configChangedArgs));
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001539 int32_t prevId = configChangedArgs.id;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001540 nsecs_t prevTimestamp = configChangedArgs.eventTime;
1541
1542 NotifyKeyArgs keyArgs;
1543 keyboard->pressAndReleaseHomeKey();
1544 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs));
1545 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
Garfield Tan1c7bc862020-01-28 13:24:04 -08001546 ASSERT_NE(prevId, keyArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001547 prevId = keyArgs.id;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001548 ASSERT_LE(prevTimestamp, keyArgs.eventTime);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001549 ASSERT_LE(keyArgs.eventTime, keyArgs.readTime);
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001550 prevTimestamp = keyArgs.eventTime;
1551
1552 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs));
1553 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
Garfield Tan1c7bc862020-01-28 13:24:04 -08001554 ASSERT_NE(prevId, keyArgs.id);
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001555 ASSERT_LE(prevTimestamp, keyArgs.eventTime);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001556 ASSERT_LE(keyArgs.eventTime, keyArgs.readTime);
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001557}
Michael Wrightd02c5b62014-02-10 15:10:22 -08001558
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001559TEST_F(InputReaderIntegrationTest, ExternalStylusesButtons) {
1560 std::unique_ptr<UinputExternalStylus> stylus = createUinputDevice<UinputExternalStylus>();
1561 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1562
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001563 const auto device = waitForDevice(stylus->getName());
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001564 ASSERT_TRUE(device.has_value());
1565
Prabir Pradhana3621852022-10-14 18:57:23 +00001566 // An external stylus with buttons should also be recognized as a keyboard.
1567 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_STYLUS, device->getSources())
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001568 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1569 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, device->getKeyboardType());
1570
1571 const auto DOWN =
1572 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD));
1573 const auto UP = AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD));
1574
1575 stylus->pressAndReleaseKey(BTN_STYLUS);
1576 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1577 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
1578 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1579 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
1580
1581 stylus->pressAndReleaseKey(BTN_STYLUS2);
1582 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1583 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_SECONDARY))));
1584 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1585 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_SECONDARY))));
1586
1587 stylus->pressAndReleaseKey(BTN_STYLUS3);
1588 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1589 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_TERTIARY))));
1590 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1591 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_TERTIARY))));
1592}
1593
Prabir Pradhan3c28b942023-08-18 20:02:01 +00001594TEST_F(InputReaderIntegrationTest, KeyboardWithStylusButtons) {
1595 std::unique_ptr<UinputKeyboard> keyboard =
1596 createUinputDevice<UinputKeyboard>("KeyboardWithStylusButtons", /*productId=*/99,
1597 std::initializer_list<int>{KEY_Q, KEY_W, KEY_E,
1598 KEY_R, KEY_T, KEY_Y,
1599 BTN_STYLUS, BTN_STYLUS2,
1600 BTN_STYLUS3});
1601 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1602
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001603 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhan3c28b942023-08-18 20:02:01 +00001604 ASSERT_TRUE(device.has_value());
1605
1606 // An alphabetical keyboard that reports stylus buttons should not be recognized as a stylus.
1607 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources())
1608 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1609 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, device->getKeyboardType());
1610}
1611
Prabir Pradhan37a819b2023-08-22 23:20:16 +00001612TEST_F(InputReaderIntegrationTest, HidUsageKeyboardIsNotAStylus) {
1613 // Create a Uinput keyboard that simulates a keyboard that can report HID usage codes. The
1614 // hid-input driver reports HID usage codes using the value for EV_MSC MSC_SCAN event.
1615 std::unique_ptr<UinputKeyboardWithHidUsage> keyboard =
1616 createUinputDevice<UinputKeyboardWithHidUsage>(
1617 std::initializer_list<int>{KEY_VOLUMEUP, KEY_VOLUMEDOWN});
1618 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1619
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001620 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhan37a819b2023-08-22 23:20:16 +00001621 ASSERT_TRUE(device.has_value());
1622
1623 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources())
1624 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1625
1626 // If a device supports reporting HID usage codes, it shouldn't automatically support
1627 // stylus keys.
1628 const std::vector<int> keycodes{AKEYCODE_STYLUS_BUTTON_PRIMARY};
1629 uint8_t outFlags[] = {0};
1630 ASSERT_TRUE(mReader->hasKeys(device->getId(), AINPUT_SOURCE_KEYBOARD, keycodes, outFlags));
1631 ASSERT_EQ(0, outFlags[0]) << "Keyboard should not have stylus button";
1632}
1633
Siarhei Vishniakoua0d2b802020-05-13 14:00:31 -07001634/**
1635 * The Steam controller sends BTN_GEAR_DOWN and BTN_GEAR_UP for the two "paddle" buttons
1636 * on the back. In this test, we make sure that BTN_GEAR_DOWN / BTN_WHEEL and BTN_GEAR_UP
1637 * are passed to the listener.
1638 */
1639static_assert(BTN_GEAR_DOWN == BTN_WHEEL);
1640TEST_F(InputReaderIntegrationTest, SendsGearDownAndUpToInputListener) {
1641 std::unique_ptr<UinputSteamController> controller = createUinputDevice<UinputSteamController>();
1642 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1643 NotifyKeyArgs keyArgs;
1644
1645 controller->pressAndReleaseKey(BTN_GEAR_DOWN);
1646 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_DOWN
1647 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_UP
1648 ASSERT_EQ(BTN_GEAR_DOWN, keyArgs.scanCode);
1649
1650 controller->pressAndReleaseKey(BTN_GEAR_UP);
1651 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_DOWN
1652 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_UP
1653 ASSERT_EQ(BTN_GEAR_UP, keyArgs.scanCode);
1654}
1655
Prabir Pradhan484d55a2022-10-14 23:17:16 +00001656// --- TouchIntegrationTest ---
1657
Arpit Singh440bf652023-08-09 09:23:43 +00001658class BaseTouchIntegrationTest : public InputReaderIntegrationTest {
Arthur Hungaab25622020-01-16 11:22:11 +08001659protected:
Arthur Hungaab25622020-01-16 11:22:11 +08001660 const std::string UNIQUE_ID = "local:0";
1661
Chris Yea52ade12020-08-27 16:49:20 -07001662 void SetUp() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001663#if !defined(__ANDROID__)
1664 GTEST_SKIP();
1665#endif
Arthur Hungaab25622020-01-16 11:22:11 +08001666 InputReaderIntegrationTest::SetUp();
1667 // At least add an internal display.
Michael Wrighta9cf4192022-12-01 23:46:39 +00001668 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
1669 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Arthur Hungaab25622020-01-16 11:22:11 +08001670
1671 mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT));
1672 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Vaibhav Devmuraric109d812024-07-10 14:21:27 +00001673 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Arthur Hungaab25622020-01-16 11:22:11 +08001674 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001675 const auto info = waitForDevice(mDevice->getName());
Prabir Pradhanda20b172022-09-26 17:01:18 +00001676 ASSERT_TRUE(info);
1677 mDeviceInfo = *info;
Arthur Hungaab25622020-01-16 11:22:11 +08001678 }
1679
Linnan Li13bf76a2024-05-05 19:18:02 +08001680 void setDisplayInfoAndReconfigure(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
Michael Wrighta9cf4192022-12-01 23:46:39 +00001681 ui::Rotation orientation, const std::string& uniqueId,
Arthur Hungaab25622020-01-16 11:22:11 +08001682 std::optional<uint8_t> physicalPort,
1683 ViewportType viewportType) {
Harry Cutts33476232023-01-30 19:57:29 +00001684 mFakePolicy->addDisplayViewport(displayId, width, height, orientation, /*isActive=*/true,
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00001685 uniqueId, physicalPort, viewportType);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001686 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hungaab25622020-01-16 11:22:11 +08001687 }
1688
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001689 void assertReceivedMotion(int32_t action, const std::vector<Point>& points) {
1690 NotifyMotionArgs args;
1691 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1692 EXPECT_EQ(action, args.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07001693 ASSERT_EQ(points.size(), args.getPointerCount());
1694 for (size_t i = 0; i < args.getPointerCount(); i++) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001695 EXPECT_EQ(points[i].x, args.pointerCoords[i].getX());
1696 EXPECT_EQ(points[i].y, args.pointerCoords[i].getY());
1697 }
1698 }
1699
Arthur Hungaab25622020-01-16 11:22:11 +08001700 std::unique_ptr<UinputTouchScreen> mDevice;
Prabir Pradhanda20b172022-09-26 17:01:18 +00001701 InputDeviceInfo mDeviceInfo;
Arthur Hungaab25622020-01-16 11:22:11 +08001702};
1703
Arpit Singh440bf652023-08-09 09:23:43 +00001704enum class TouchIntegrationTestDisplays { DISPLAY_INTERNAL, DISPLAY_INPUT_PORT, DISPLAY_UNIQUE_ID };
1705
1706class TouchIntegrationTest : public BaseTouchIntegrationTest,
1707 public testing::WithParamInterface<TouchIntegrationTestDisplays> {
1708protected:
1709 static constexpr std::optional<uint8_t> DISPLAY_PORT = 0;
1710 const std::string INPUT_PORT = "uinput_touch/input0";
1711
1712 void SetUp() override {
1713#if !defined(__ANDROID__)
1714 GTEST_SKIP();
1715#endif
1716 if (GetParam() == TouchIntegrationTestDisplays::DISPLAY_INTERNAL) {
1717 BaseTouchIntegrationTest::SetUp();
1718 return;
1719 }
1720
1721 // setup policy with a input-port or UniqueId association to the display
1722 bool isInputPortAssociation =
1723 GetParam() == TouchIntegrationTestDisplays::DISPLAY_INPUT_PORT;
1724
1725 mFakePolicy = sp<FakeInputReaderPolicy>::make();
1726 if (isInputPortAssociation) {
1727 mFakePolicy->addInputPortAssociation(INPUT_PORT, DISPLAY_PORT.value());
1728 } else {
1729 mFakePolicy->addInputUniqueIdAssociation(INPUT_PORT, UNIQUE_ID);
1730 }
Arpit Singh440bf652023-08-09 09:23:43 +00001731
1732 InputReaderIntegrationTest::setupInputReader();
1733
1734 mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT),
1735 INPUT_PORT);
1736 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1737
1738 // Add a display linked to a physical port or UniqueId.
1739 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
1740 UNIQUE_ID, isInputPortAssociation ? DISPLAY_PORT : NO_PORT,
1741 ViewportType::INTERNAL);
1742 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Vaibhav Devmuraric109d812024-07-10 14:21:27 +00001743 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Arpit Singh440bf652023-08-09 09:23:43 +00001744 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001745 const auto info = waitForDevice(mDevice->getName());
Arpit Singh440bf652023-08-09 09:23:43 +00001746 ASSERT_TRUE(info);
1747 mDeviceInfo = *info;
1748 }
1749};
1750
1751TEST_P(TouchIntegrationTest, MultiTouchDeviceSource) {
Prabir Pradhanf9a41282022-10-25 17:15:50 +00001752 // The UinputTouchScreen is an MT device that supports MT_TOOL_TYPE and also supports stylus
1753 // buttons. It should show up as a touchscreen, stylus, and keyboard (for reporting button
1754 // presses).
1755 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD,
1756 mDeviceInfo.getSources());
1757}
1758
Arpit Singh440bf652023-08-09 09:23:43 +00001759TEST_P(TouchIntegrationTest, InputEvent_ProcessSingleTouch) {
Arthur Hungaab25622020-01-16 11:22:11 +08001760 NotifyMotionArgs args;
1761 const Point centerPoint = mDevice->getCenterPoint();
1762
1763 // ACTION_DOWN
Arthur Hung9ad18942021-06-19 02:04:46 +00001764 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001765 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001766 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001767 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1768 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1769
1770 // ACTION_MOVE
1771 mDevice->sendMove(centerPoint + Point(1, 1));
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001772 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001773 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1774 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1775
1776 // ACTION_UP
1777 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001778 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001779 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1780 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
1781}
1782
Arpit Singh440bf652023-08-09 09:23:43 +00001783TEST_P(TouchIntegrationTest, InputEvent_ProcessMultiTouch) {
Arthur Hungaab25622020-01-16 11:22:11 +08001784 NotifyMotionArgs args;
1785 const Point centerPoint = mDevice->getCenterPoint();
1786
1787 // ACTION_DOWN
Arthur Hung9ad18942021-06-19 02:04:46 +00001788 mDevice->sendSlot(FIRST_SLOT);
1789 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001790 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001791 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001792 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1793 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1794
1795 // ACTION_POINTER_DOWN (Second slot)
1796 const Point secondPoint = centerPoint + Point(100, 100);
1797 mDevice->sendSlot(SECOND_SLOT);
1798 mDevice->sendTrackingId(SECOND_TRACKING_ID);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001799 mDevice->sendDown(secondPoint);
1800 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001801 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001802 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001803
1804 // ACTION_MOVE (Second slot)
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001805 mDevice->sendMove(secondPoint + Point(1, 1));
1806 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001807 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1808 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1809
1810 // ACTION_POINTER_UP (Second slot)
arthurhungcc7f9802020-04-30 17:55:40 +08001811 mDevice->sendPointerUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001812 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001813 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001814 ASSERT_EQ(ACTION_POINTER_1_UP, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001815
1816 // ACTION_UP
1817 mDevice->sendSlot(FIRST_SLOT);
1818 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001819 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001820 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1821 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
1822}
1823
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001824/**
1825 * What happens when a pointer goes up while another pointer moves in the same frame? Are POINTER_UP
1826 * events guaranteed to contain the same data as a preceding MOVE, or can they contain different
1827 * data?
1828 * In this test, we try to send a change in coordinates in Pointer 0 in the same frame as the
1829 * liftoff of Pointer 1. We check that POINTER_UP event is generated first, and the MOVE event
1830 * for Pointer 0 only is generated after.
1831 * Suppose we are only interested in learning the movement of Pointer 0. If we only observe MOVE
1832 * events, we will not miss any information.
1833 * Even though the Pointer 1 up event contains updated Pointer 0 coordinates, there is another MOVE
1834 * event generated afterwards that contains the newest movement of pointer 0.
1835 * This is important for palm rejection. If there is a subsequent InputListener stage that detects
1836 * palms, and wants to cancel Pointer 1, then it is safe to simply drop POINTER_1_UP event without
1837 * losing information about non-palm pointers.
1838 */
Arpit Singh440bf652023-08-09 09:23:43 +00001839TEST_P(TouchIntegrationTest, MultiTouch_PointerMoveAndSecondPointerUp) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001840 NotifyMotionArgs args;
1841 const Point centerPoint = mDevice->getCenterPoint();
1842
1843 // ACTION_DOWN
1844 mDevice->sendSlot(FIRST_SLOT);
1845 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1846 mDevice->sendDown(centerPoint);
1847 mDevice->sendSync();
1848 assertReceivedMotion(AMOTION_EVENT_ACTION_DOWN, {centerPoint});
1849
1850 // ACTION_POINTER_DOWN (Second slot)
1851 const Point secondPoint = centerPoint + Point(100, 100);
1852 mDevice->sendSlot(SECOND_SLOT);
1853 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1854 mDevice->sendDown(secondPoint);
1855 mDevice->sendSync();
1856 assertReceivedMotion(ACTION_POINTER_1_DOWN, {centerPoint, secondPoint});
1857
1858 // ACTION_MOVE (First slot)
1859 mDevice->sendSlot(FIRST_SLOT);
1860 mDevice->sendMove(centerPoint + Point(5, 5));
1861 // ACTION_POINTER_UP (Second slot)
1862 mDevice->sendSlot(SECOND_SLOT);
1863 mDevice->sendPointerUp();
1864 // Send a single sync for the above 2 pointer updates
1865 mDevice->sendSync();
1866
1867 // First, we should get POINTER_UP for the second pointer
1868 assertReceivedMotion(ACTION_POINTER_1_UP,
1869 {/*first pointer */ centerPoint + Point(5, 5),
1870 /*second pointer*/ secondPoint});
1871
1872 // Next, the MOVE event for the first pointer
1873 assertReceivedMotion(AMOTION_EVENT_ACTION_MOVE, {centerPoint + Point(5, 5)});
1874}
1875
1876/**
1877 * Similar scenario as above. The difference is that when the second pointer goes up, it will first
1878 * move, and then it will go up, all in the same frame.
1879 * In this scenario, the movement of the second pointer just prior to liftoff is ignored, and never
1880 * gets sent to the listener.
1881 */
Arpit Singh440bf652023-08-09 09:23:43 +00001882TEST_P(TouchIntegrationTest, MultiTouch_PointerMoveAndSecondPointerMoveAndUp) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001883 NotifyMotionArgs args;
1884 const Point centerPoint = mDevice->getCenterPoint();
1885
1886 // ACTION_DOWN
1887 mDevice->sendSlot(FIRST_SLOT);
1888 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1889 mDevice->sendDown(centerPoint);
1890 mDevice->sendSync();
1891 assertReceivedMotion(AMOTION_EVENT_ACTION_DOWN, {centerPoint});
1892
1893 // ACTION_POINTER_DOWN (Second slot)
1894 const Point secondPoint = centerPoint + Point(100, 100);
1895 mDevice->sendSlot(SECOND_SLOT);
1896 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1897 mDevice->sendDown(secondPoint);
1898 mDevice->sendSync();
1899 assertReceivedMotion(ACTION_POINTER_1_DOWN, {centerPoint, secondPoint});
1900
1901 // ACTION_MOVE (First slot)
1902 mDevice->sendSlot(FIRST_SLOT);
1903 mDevice->sendMove(centerPoint + Point(5, 5));
1904 // ACTION_POINTER_UP (Second slot)
1905 mDevice->sendSlot(SECOND_SLOT);
1906 mDevice->sendMove(secondPoint + Point(6, 6));
1907 mDevice->sendPointerUp();
1908 // Send a single sync for the above 2 pointer updates
1909 mDevice->sendSync();
1910
1911 // First, we should get POINTER_UP for the second pointer
1912 // The movement of the second pointer during the liftoff frame is ignored.
1913 // The coordinates 'secondPoint + Point(6, 6)' are never sent to the listener.
1914 assertReceivedMotion(ACTION_POINTER_1_UP,
1915 {/*first pointer */ centerPoint + Point(5, 5),
1916 /*second pointer*/ secondPoint});
1917
1918 // Next, the MOVE event for the first pointer
1919 assertReceivedMotion(AMOTION_EVENT_ACTION_MOVE, {centerPoint + Point(5, 5)});
1920}
1921
Arpit Singh440bf652023-08-09 09:23:43 +00001922TEST_P(TouchIntegrationTest, InputEvent_ProcessPalm) {
Arthur Hungaab25622020-01-16 11:22:11 +08001923 NotifyMotionArgs args;
1924 const Point centerPoint = mDevice->getCenterPoint();
1925
1926 // ACTION_DOWN
arthurhungcc7f9802020-04-30 17:55:40 +08001927 mDevice->sendSlot(FIRST_SLOT);
1928 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001929 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001930 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001931 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1932 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1933
arthurhungcc7f9802020-04-30 17:55:40 +08001934 // ACTION_POINTER_DOWN (second slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001935 const Point secondPoint = centerPoint + Point(100, 100);
1936 mDevice->sendSlot(SECOND_SLOT);
1937 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1938 mDevice->sendDown(secondPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001939 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001940 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001941 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001942
arthurhungcc7f9802020-04-30 17:55:40 +08001943 // ACTION_MOVE (second slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001944 mDevice->sendMove(secondPoint + Point(1, 1));
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001945 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001946 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1947 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1948
arthurhungcc7f9802020-04-30 17:55:40 +08001949 // Send MT_TOOL_PALM (second slot), which indicates that the touch IC has determined this to be
1950 // a palm event.
1951 // Expect to receive the ACTION_POINTER_UP with cancel flag.
Arthur Hungaab25622020-01-16 11:22:11 +08001952 mDevice->sendToolType(MT_TOOL_PALM);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001953 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001954 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001955 ASSERT_EQ(ACTION_POINTER_1_UP, args.action);
arthurhungcc7f9802020-04-30 17:55:40 +08001956 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, args.flags);
Arthur Hungaab25622020-01-16 11:22:11 +08001957
arthurhungcc7f9802020-04-30 17:55:40 +08001958 // Send up to second slot, expect first slot send moving.
1959 mDevice->sendPointerUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001960 mDevice->sendSync();
arthurhungcc7f9802020-04-30 17:55:40 +08001961 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1962 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001963
arthurhungcc7f9802020-04-30 17:55:40 +08001964 // Send ACTION_UP (first slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001965 mDevice->sendSlot(FIRST_SLOT);
1966 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001967 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001968
arthurhungcc7f9802020-04-30 17:55:40 +08001969 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1970 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001971}
1972
Prabir Pradhanc09ec6d2023-08-14 22:31:43 +00001973/**
1974 * Some drivers historically have reported axis values outside of the range specified in the
1975 * evdev axis info. Ensure we don't crash when this happens. For example, a driver may report a
1976 * pressure value greater than the reported maximum, since it unclear what specific meaning the
1977 * maximum value for pressure has (beyond the maximum value that can be produced by a sensor),
1978 * and no units for pressure (resolution) is specified by the evdev documentation.
1979 */
1980TEST_P(TouchIntegrationTest, AcceptsAxisValuesOutsideReportedRange) {
1981 const Point centerPoint = mDevice->getCenterPoint();
1982
1983 // Down with pressure outside the reported range
1984 mDevice->sendSlot(FIRST_SLOT);
1985 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1986 mDevice->sendDown(centerPoint);
1987 mDevice->sendPressure(UinputTouchScreen::RAW_PRESSURE_MAX + 2);
1988 mDevice->sendSync();
1989 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1990 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
1991
1992 // Move to a point outside the reported range
1993 mDevice->sendMove(Point(DISPLAY_WIDTH, DISPLAY_HEIGHT) + Point(1, 1));
1994 mDevice->sendSync();
1995 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1996 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
1997
1998 // Up
1999 mDevice->sendUp();
2000 mDevice->sendSync();
2001 ASSERT_NO_FATAL_FAILURE(
2002 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2003}
2004
Arpit Singh440bf652023-08-09 09:23:43 +00002005TEST_P(TouchIntegrationTest, NotifiesPolicyWhenStylusGestureStarted) {
Prabir Pradhanda20b172022-09-26 17:01:18 +00002006 const Point centerPoint = mDevice->getCenterPoint();
2007
2008 // Send down with the pen tool selected. The policy should be notified of the stylus presence.
2009 mDevice->sendSlot(FIRST_SLOT);
2010 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2011 mDevice->sendToolType(MT_TOOL_PEN);
2012 mDevice->sendDown(centerPoint);
2013 mDevice->sendSync();
2014 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2015 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002016 WithToolType(ToolType::STYLUS))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00002017
2018 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotified(mDeviceInfo.getId()));
2019
2020 // Release the stylus touch.
2021 mDevice->sendUp();
2022 mDevice->sendSync();
2023 ASSERT_NO_FATAL_FAILURE(
2024 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2025
2026 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotNotified());
2027
2028 // Touch down with the finger, without the pen tool selected. The policy is not notified.
2029 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2030 mDevice->sendToolType(MT_TOOL_FINGER);
2031 mDevice->sendDown(centerPoint);
2032 mDevice->sendSync();
2033 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2034 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002035 WithToolType(ToolType::FINGER))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00002036
2037 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotNotified());
2038
2039 mDevice->sendUp();
2040 mDevice->sendSync();
2041 ASSERT_NO_FATAL_FAILURE(
2042 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2043
2044 // Send a move event with the stylus tool without BTN_TOUCH to generate a hover enter.
2045 // The policy should be notified of the stylus presence.
2046 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2047 mDevice->sendToolType(MT_TOOL_PEN);
2048 mDevice->sendMove(centerPoint);
2049 mDevice->sendSync();
2050 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2051 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002052 WithToolType(ToolType::STYLUS))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00002053
2054 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotified(mDeviceInfo.getId()));
2055}
2056
Arpit Singh440bf652023-08-09 09:23:43 +00002057TEST_P(TouchIntegrationTest, ExternalStylusConnectedDuringTouchGesture) {
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002058 const Point centerPoint = mDevice->getCenterPoint();
2059
2060 // Down
2061 mDevice->sendSlot(FIRST_SLOT);
2062 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2063 mDevice->sendDown(centerPoint);
2064 mDevice->sendSync();
2065 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2066 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
2067
2068 // Move
2069 mDevice->sendMove(centerPoint + Point(1, 1));
2070 mDevice->sendSync();
2071 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2072 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
2073
2074 // Connecting an external stylus mid-gesture should not interrupt the ongoing gesture stream.
2075 auto externalStylus = createUinputDevice<UinputExternalStylus>();
2076 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Vaibhav Devmuraric109d812024-07-10 14:21:27 +00002077 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002078 const auto stylusInfo = waitForDevice(externalStylus->getName());
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002079 ASSERT_TRUE(stylusInfo);
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002080
2081 // Move
2082 mDevice->sendMove(centerPoint + Point(2, 2));
2083 mDevice->sendSync();
2084 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2085 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
2086
2087 // Disconnecting an external stylus mid-gesture should not interrupt the ongoing gesture stream.
2088 externalStylus.reset();
2089 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Vaibhav Devmuraric109d812024-07-10 14:21:27 +00002090 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002091 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2092
2093 // Up
2094 mDevice->sendUp();
2095 mDevice->sendSync();
2096 ASSERT_NO_FATAL_FAILURE(
2097 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2098
2099 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2100}
2101
Arpit Singh440bf652023-08-09 09:23:43 +00002102INSTANTIATE_TEST_SUITE_P(TouchIntegrationTestDisplayVariants, TouchIntegrationTest,
2103 testing::Values(TouchIntegrationTestDisplays::DISPLAY_INTERNAL,
2104 TouchIntegrationTestDisplays::DISPLAY_INPUT_PORT,
2105 TouchIntegrationTestDisplays::DISPLAY_UNIQUE_ID));
2106
Prabir Pradhan124ea442022-10-28 20:27:44 +00002107// --- StylusButtonIntegrationTest ---
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002108
Prabir Pradhan124ea442022-10-28 20:27:44 +00002109// Verify the behavior of button presses reported by various kinds of styluses, including buttons
2110// reported by the touchscreen's device, by a fused external stylus, and by an un-fused external
2111// stylus.
2112template <typename UinputStylusDevice>
Arpit Singh440bf652023-08-09 09:23:43 +00002113class StylusButtonIntegrationTest : public BaseTouchIntegrationTest {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002114protected:
2115 void SetUp() override {
2116#if !defined(__ANDROID__)
2117 GTEST_SKIP();
2118#endif
Arpit Singh440bf652023-08-09 09:23:43 +00002119 BaseTouchIntegrationTest::SetUp();
Prabir Pradhan124ea442022-10-28 20:27:44 +00002120 mTouchscreen = mDevice.get();
2121 mTouchscreenInfo = mDeviceInfo;
2122
2123 setUpStylusDevice();
2124 }
2125
2126 UinputStylusDevice* mStylus{nullptr};
2127 InputDeviceInfo mStylusInfo{};
2128
2129 UinputTouchScreen* mTouchscreen{nullptr};
2130 InputDeviceInfo mTouchscreenInfo{};
2131
2132private:
2133 // When we are attempting to test stylus button events that are sent from the touchscreen,
2134 // use the same Uinput device for the touchscreen and the stylus.
2135 template <typename T = UinputStylusDevice>
2136 std::enable_if_t<std::is_same_v<UinputTouchScreen, T>, void> setUpStylusDevice() {
2137 mStylus = mDevice.get();
2138 mStylusInfo = mDeviceInfo;
2139 }
2140
2141 // When we are attempting to stylus buttons from an external stylus being merged with touches
2142 // from a touchscreen, create a new Uinput device through which stylus buttons can be injected.
2143 template <typename T = UinputStylusDevice>
2144 std::enable_if_t<!std::is_same_v<UinputTouchScreen, T>, void> setUpStylusDevice() {
2145 mStylusDeviceLifecycleTracker = createUinputDevice<T>();
2146 mStylus = mStylusDeviceLifecycleTracker.get();
2147 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Vaibhav Devmuraric109d812024-07-10 14:21:27 +00002148 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Prabir Pradhan124ea442022-10-28 20:27:44 +00002149 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002150 const auto info = waitForDevice(mStylus->getName());
Prabir Pradhan124ea442022-10-28 20:27:44 +00002151 ASSERT_TRUE(info);
2152 mStylusInfo = *info;
2153 }
2154
2155 std::unique_ptr<UinputStylusDevice> mStylusDeviceLifecycleTracker{};
2156
2157 // Hide the base class's device to expose it with a different name for readability.
Arpit Singh440bf652023-08-09 09:23:43 +00002158 using BaseTouchIntegrationTest::mDevice;
2159 using BaseTouchIntegrationTest::mDeviceInfo;
Prabir Pradhan124ea442022-10-28 20:27:44 +00002160};
2161
2162using StylusButtonIntegrationTestTypes =
2163 ::testing::Types<UinputTouchScreen, UinputExternalStylus, UinputExternalStylusWithPressure>;
2164TYPED_TEST_SUITE(StylusButtonIntegrationTest, StylusButtonIntegrationTestTypes);
2165
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002166TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsGenerateKeyEvents) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002167 const auto stylusId = TestFixture::mStylusInfo.getId();
2168
2169 TestFixture::mStylus->pressKey(BTN_STYLUS);
2170 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2171 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2172 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2173
2174 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2175 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002176 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002177 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002178}
2179
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002180TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingTouchGesture) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002181 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2182 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2183 const auto stylusId = TestFixture::mStylusInfo.getId();
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002184
2185 // Press the stylus button.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002186 TestFixture::mStylus->pressKey(BTN_STYLUS);
2187 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002188 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002189 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002190
2191 // Start and finish a stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002192 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2193 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2194 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2195 TestFixture::mTouchscreen->sendDown(centerPoint);
2196 TestFixture::mTouchscreen->sendSync();
2197 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002198 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002199 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002200 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2201 WithDeviceId(touchscreenId))));
2202 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002203 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002204 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002205 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2206 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002207
Prabir Pradhan124ea442022-10-28 20:27:44 +00002208 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2209 TestFixture::mTouchscreen->sendSync();
2210 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002211 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002212 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002213 WithDeviceId(touchscreenId))));
2214 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002215 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002216 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002217 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002218
2219 // Release the stylus button.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002220 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2221 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002222 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002223 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002224}
2225
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002226TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingHoveringTouchGesture) {
Prabir Pradhan9a561c22022-11-07 16:11:23 +00002227 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2228 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2229 const auto stylusId = TestFixture::mStylusInfo.getId();
2230 auto toolTypeDevice =
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002231 AllOf(WithToolType(ToolType::STYLUS), WithDeviceId(touchscreenId));
Prabir Pradhan9a561c22022-11-07 16:11:23 +00002232
2233 // Press the stylus button.
2234 TestFixture::mStylus->pressKey(BTN_STYLUS);
2235 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2236 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2237 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2238
2239 // Start hovering with the stylus.
2240 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2241 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2242 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2243 TestFixture::mTouchscreen->sendMove(centerPoint);
2244 TestFixture::mTouchscreen->sendSync();
2245 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2246 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2247 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2248 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2249 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2250 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2251 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2252 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
2253 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2254
2255 // Touch down with the stylus.
2256 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2257 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2258 TestFixture::mTouchscreen->sendDown(centerPoint);
2259 TestFixture::mTouchscreen->sendSync();
2260 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2261 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
2262 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2263
2264 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2265 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
2266 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2267
2268 // Stop touching with the stylus, and start hovering.
2269 TestFixture::mTouchscreen->sendUp();
2270 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2271 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2272 TestFixture::mTouchscreen->sendMove(centerPoint);
2273 TestFixture::mTouchscreen->sendSync();
2274 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2275 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_UP),
2276 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2277 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2278 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2279 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2280 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2281 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2282 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2283
2284 // Stop hovering.
2285 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2286 TestFixture::mTouchscreen->sendSync();
2287 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2288 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
2289 WithButtonState(0))));
2290 // TODO(b/257971675): Fix inconsistent button state when exiting hover.
2291 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2292 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
2293 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2294
2295 // Release the stylus button.
2296 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2297 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2298 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
2299 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2300}
2301
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002302TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsWithinTouchGesture) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002303 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2304 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2305 const auto stylusId = TestFixture::mStylusInfo.getId();
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002306
2307 // Start a stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002308 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2309 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2310 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2311 TestFixture::mTouchscreen->sendDown(centerPoint);
2312 TestFixture::mTouchscreen->sendSync();
2313 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002314 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002315 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002316 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002317
2318 // Press and release a stylus button. Each change in button state also generates a MOVE event.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002319 TestFixture::mStylus->pressKey(BTN_STYLUS);
2320 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002321 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002322 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2323 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002324 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002325 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002326 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2327 WithDeviceId(touchscreenId))));
2328 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002329 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002330 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002331 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2332 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002333
Prabir Pradhan124ea442022-10-28 20:27:44 +00002334 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2335 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002336 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002337 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2338 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002339 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002340 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002341 WithDeviceId(touchscreenId))));
2342 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002343 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002344 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002345 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002346
2347 // Finish the stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002348 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2349 TestFixture::mTouchscreen->sendSync();
2350 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002351 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002352 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002353 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002354}
2355
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002356TYPED_TEST(StylusButtonIntegrationTest, StylusButtonMotionEventsDisabled) {
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002357 TestFixture::mFakePolicy->setStylusButtonMotionEventsEnabled(false);
2358 TestFixture::mReader->requestRefreshConfiguration(
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002359 InputReaderConfiguration::Change::STYLUS_BUTTON_REPORTING);
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002360
2361 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2362 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2363 const auto stylusId = TestFixture::mStylusInfo.getId();
2364
2365 // Start a stylus gesture. By the time this event is processed, the configuration change that
2366 // was requested is guaranteed to be completed.
2367 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2368 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2369 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2370 TestFixture::mTouchscreen->sendDown(centerPoint);
2371 TestFixture::mTouchscreen->sendSync();
2372 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2373 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002374 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002375 WithDeviceId(touchscreenId))));
2376
2377 // Press and release a stylus button. Each change only generates a MOVE motion event.
2378 // Key events are unaffected.
2379 TestFixture::mStylus->pressKey(BTN_STYLUS);
2380 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2381 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2382 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2383 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2384 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002385 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002386 WithDeviceId(touchscreenId))));
2387
2388 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2389 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2390 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
2391 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2392 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2393 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002394 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002395 WithDeviceId(touchscreenId))));
2396
2397 // Finish the stylus gesture.
2398 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2399 TestFixture::mTouchscreen->sendSync();
2400 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2401 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002402 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002403 WithDeviceId(touchscreenId))));
2404}
2405
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002406// --- ExternalStylusIntegrationTest ---
2407
2408// Verify the behavior of an external stylus. An external stylus can report pressure or button
2409// data independently of the touchscreen, which is then sent as a MotionEvent as part of an
2410// ongoing stylus gesture that is being emitted by the touchscreen.
Arpit Singh440bf652023-08-09 09:23:43 +00002411using ExternalStylusIntegrationTest = BaseTouchIntegrationTest;
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002412
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002413TEST_F(ExternalStylusIntegrationTest, ExternalStylusConnectionChangesTouchscreenSource) {
2414 // Create an external stylus capable of reporting pressure data that
2415 // should be fused with a touch pointer.
2416 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2417 createUinputDevice<UinputExternalStylusWithPressure>();
2418 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Vaibhav Devmuraric109d812024-07-10 14:21:27 +00002419 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002420 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002421 ASSERT_TRUE(stylusInfo);
2422
2423 // Connecting an external stylus changes the source of the touchscreen.
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002424 const auto deviceInfo = waitForDevice(mDevice->getName());
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002425 ASSERT_TRUE(deviceInfo);
2426 ASSERT_TRUE(isFromSource(deviceInfo->getSources(), STYLUS_FUSION_SOURCE));
2427}
2428
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002429TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureReported) {
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002430 const Point centerPoint = mDevice->getCenterPoint();
2431
2432 // Create an external stylus capable of reporting pressure data that
2433 // should be fused with a touch pointer.
2434 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2435 createUinputDevice<UinputExternalStylusWithPressure>();
2436 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Vaibhav Devmuraric109d812024-07-10 14:21:27 +00002437 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002438 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002439 ASSERT_TRUE(stylusInfo);
2440
2441 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2442
2443 const auto touchscreenId = mDeviceInfo.getId();
2444
2445 // Set a pressure value on the stylus. It doesn't generate any events.
2446 const auto& RAW_PRESSURE_MAX = UinputExternalStylusWithPressure::RAW_PRESSURE_MAX;
2447 stylus->setPressure(100);
2448 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2449
2450 // Start a finger gesture, and ensure it shows up as stylus gesture
2451 // with the pressure set by the external stylus.
Dominik Laskowski2f01d772022-03-23 16:01:29 -07002452 mDevice->sendSlot(FIRST_SLOT);
Chris Ye1b0c7342020-07-28 21:57:03 -07002453 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002454 mDevice->sendToolType(MT_TOOL_FINGER);
Prabir Pradhanb54ffb22022-10-27 18:03:34 +00002455 mDevice->sendDown(centerPoint);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002456 mDevice->sendSync();
2457 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002458 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithToolType(ToolType::STYLUS),
2459 WithButtonState(0), WithSource(STYLUS_FUSION_SOURCE), WithDeviceId(touchscreenId),
2460 WithPressure(100.f / RAW_PRESSURE_MAX))));
Dominik Laskowski2f01d772022-03-23 16:01:29 -07002461
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002462 // Change the pressure on the external stylus, and ensure the touchscreen generates a MOVE
2463 // event with the updated pressure.
2464 stylus->setPressure(200);
Vaibhav Devmuraridd82b8e2022-08-16 15:34:01 +00002465 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002466 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithToolType(ToolType::STYLUS),
2467 WithButtonState(0), WithSource(STYLUS_FUSION_SOURCE), WithDeviceId(touchscreenId),
2468 WithPressure(200.f / RAW_PRESSURE_MAX))));
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002469
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002470 // The external stylus did not generate any events.
2471 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2472 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
2473}
2474
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002475TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureNotReported) {
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002476 const Point centerPoint = mDevice->getCenterPoint();
2477
2478 // Create an external stylus capable of reporting pressure data that
2479 // should be fused with a touch pointer.
2480 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2481 createUinputDevice<UinputExternalStylusWithPressure>();
2482 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Vaibhav Devmuraric109d812024-07-10 14:21:27 +00002483 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002484 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002485 ASSERT_TRUE(stylusInfo);
2486
2487 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2488
2489 const auto touchscreenId = mDeviceInfo.getId();
2490
2491 // Set a pressure value of 0 on the stylus. It doesn't generate any events.
2492 const auto& RAW_PRESSURE_MAX = UinputExternalStylusWithPressure::RAW_PRESSURE_MAX;
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002493 // Send a non-zero value first to prevent the kernel from consuming the zero event.
2494 stylus->setPressure(100);
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002495 stylus->setPressure(0);
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002496 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002497
2498 // Start a finger gesture. The touch device will withhold generating any touches for
2499 // up to 72 milliseconds while waiting for pressure data from the external stylus.
2500 mDevice->sendSlot(FIRST_SLOT);
2501 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2502 mDevice->sendToolType(MT_TOOL_FINGER);
2503 mDevice->sendDown(centerPoint);
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002504 const auto syncTime = std::chrono::system_clock::now();
2505 // After 72 ms, the event *will* be generated. If we wait the full 72 ms to check that NO event
2506 // is generated in that period, there will be a race condition between the event being generated
2507 // and the test's wait timeout expiring. Thus, we wait for a shorter duration in the test, which
2508 // will reduce the liklihood of the race condition occurring.
2509 const auto waitUntilTimeForNoEvent =
2510 syncTime + std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT / 2));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07002511 mDevice->sendSync();
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002512 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled(waitUntilTimeForNoEvent));
Michael Wrightd02c5b62014-02-10 15:10:22 -08002513
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002514 // Since the external stylus did not report a pressure value within the timeout,
2515 // it shows up as a finger pointer.
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002516 const auto waitUntilTimeForEvent = syncTime +
2517 std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT)) + EVENT_HAPPENED_TIMEOUT;
2518 ASSERT_NO_FATAL_FAILURE(
2519 mTestListener->assertNotifyMotionWasCalled(AllOf(WithMotionAction(
2520 AMOTION_EVENT_ACTION_DOWN),
2521 WithSource(AINPUT_SOURCE_TOUCHSCREEN |
2522 AINPUT_SOURCE_STYLUS),
2523 WithToolType(ToolType::FINGER),
2524 WithDeviceId(touchscreenId),
2525 WithPressure(1.f)),
2526 waitUntilTimeForEvent));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002527
2528 // Change the pressure on the external stylus. Since the pressure was not present at the start
2529 // of the gesture, it is ignored for now.
2530 stylus->setPressure(200);
2531 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2532
2533 // Finish the finger gesture.
Michael Wrightd02c5b62014-02-10 15:10:22 -08002534 mDevice->sendTrackingId(INVALID_TRACKING_ID);
2535 mDevice->sendSync();
2536 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2537 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002538 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002539 WithToolType(ToolType::FINGER))));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002540
2541 // Start a new gesture. Since we have a valid pressure value, it shows up as a stylus.
2542 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2543 mDevice->sendToolType(MT_TOOL_FINGER);
2544 mDevice->sendDown(centerPoint);
2545 mDevice->sendSync();
2546 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002547 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithSource(STYLUS_FUSION_SOURCE),
2548 WithToolType(ToolType::STYLUS), WithButtonState(0), WithDeviceId(touchscreenId),
2549 WithPressure(200.f / RAW_PRESSURE_MAX))));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002550
2551 // The external stylus did not generate any events.
2552 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2553 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002554}
Siarhei Vishniakou1983a712021-06-04 19:27:09 +00002555
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002556TEST_F(ExternalStylusIntegrationTest, UnfusedExternalStylus) {
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002557 const Point centerPoint = mDevice->getCenterPoint();
2558
2559 // Create an external stylus device that does not support pressure. It should not affect any
2560 // touch pointers.
2561 std::unique_ptr<UinputExternalStylus> stylus = createUinputDevice<UinputExternalStylus>();
2562 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Vaibhav Devmuraric109d812024-07-10 14:21:27 +00002563 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertConfigurationChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002564 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002565 ASSERT_TRUE(stylusInfo);
2566
2567 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2568
2569 const auto touchscreenId = mDeviceInfo.getId();
2570
2571 // Start a finger gesture and ensure a finger pointer is generated for it, without waiting for
2572 // pressure data from the external stylus.
2573 mDevice->sendSlot(FIRST_SLOT);
2574 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2575 mDevice->sendToolType(MT_TOOL_FINGER);
2576 mDevice->sendDown(centerPoint);
2577 auto waitUntil = std::chrono::system_clock::now() +
2578 std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT));
2579 mDevice->sendSync();
2580 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002581 mTestListener->assertNotifyMotionWasCalled(AllOf(WithMotionAction(
2582 AMOTION_EVENT_ACTION_DOWN),
2583 WithToolType(ToolType::FINGER),
2584 WithSource(AINPUT_SOURCE_TOUCHSCREEN |
2585 AINPUT_SOURCE_STYLUS),
2586 WithButtonState(0),
2587 WithDeviceId(touchscreenId),
2588 WithPressure(1.f)),
2589 waitUntil));
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002590
2591 // The external stylus did not generate any events.
2592 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2593 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
2594}
2595
Michael Wrightd02c5b62014-02-10 15:10:22 -08002596// --- InputDeviceTest ---
2597class InputDeviceTest : public testing::Test {
2598protected:
2599 static const char* DEVICE_NAME;
2600 static const char* DEVICE_LOCATION;
2601 static const int32_t DEVICE_ID;
2602 static const int32_t DEVICE_GENERATION;
2603 static const int32_t DEVICE_CONTROLLER_NUMBER;
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002604 static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002605 static const int32_t EVENTHUB_ID;
2606 static const std::string DEVICE_BLUETOOTH_ADDRESS;
2607
2608 std::shared_ptr<FakeEventHub> mFakeEventHub;
2609 sp<FakeInputReaderPolicy> mFakePolicy;
2610 std::unique_ptr<TestInputListener> mFakeListener;
2611 std::unique_ptr<InstrumentedInputReader> mReader;
2612 std::shared_ptr<InputDevice> mDevice;
2613
2614 void SetUp() override {
2615 mFakeEventHub = std::make_unique<FakeEventHub>();
2616 mFakePolicy = sp<FakeInputReaderPolicy>::make();
2617 mFakeListener = std::make_unique<TestInputListener>();
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002618 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Michael Wrightd02c5b62014-02-10 15:10:22 -08002619 *mFakeListener);
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002620 InputDeviceIdentifier identifier;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002621 identifier.name = DEVICE_NAME;
2622 identifier.location = DEVICE_LOCATION;
2623 identifier.bluetoothAddress = DEVICE_BLUETOOTH_ADDRESS;
2624 mDevice = std::make_shared<InputDevice>(mReader->getContext(), DEVICE_ID, DEVICE_GENERATION,
2625 identifier);
2626 mReader->pushNextDevice(mDevice);
2627 mFakeEventHub->addDevice(EVENTHUB_ID, DEVICE_NAME, ftl::Flags<InputDeviceClass>(0));
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002628 mReader->loopOnce();
Michael Wrightd02c5b62014-02-10 15:10:22 -08002629 }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002630
2631 void TearDown() override {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002632 mFakeListener.reset();
2633 mFakePolicy.clear();
2634 }
2635};
2636
2637const char* InputDeviceTest::DEVICE_NAME = "device";
2638const char* InputDeviceTest::DEVICE_LOCATION = "USB1";
2639const int32_t InputDeviceTest::DEVICE_ID = END_RESERVED_ID + 1000;
2640const int32_t InputDeviceTest::DEVICE_GENERATION = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002641const int32_t InputDeviceTest::DEVICE_CONTROLLER_NUMBER = 0;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002642const ftl::Flags<InputDeviceClass> InputDeviceTest::DEVICE_CLASSES =
2643 InputDeviceClass::KEYBOARD | InputDeviceClass::TOUCH | InputDeviceClass::JOYSTICK;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002644const int32_t InputDeviceTest::EVENTHUB_ID = 1;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002645const std::string InputDeviceTest::DEVICE_BLUETOOTH_ADDRESS = "11:AA:22:BB:33:CC";
2646
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002647TEST_F(InputDeviceTest, ImmutableProperties) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002648 ASSERT_EQ(DEVICE_ID, mDevice->getId());
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002649 ASSERT_STREQ(DEVICE_NAME, mDevice->getName().c_str());
2650 ASSERT_EQ(ftl::Flags<InputDeviceClass>(0), mDevice->getClasses());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002651}
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002652
Michael Wrightd02c5b62014-02-10 15:10:22 -08002653TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsFalse) {
2654 ASSERT_EQ(mDevice->isEnabled(), false);
2655}
2656
2657TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
2658 // Configuration.
2659 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002660 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002661
2662 // Reset.
2663 unused += mDevice->reset(ARBITRARY_TIME);
2664
2665 NotifyDeviceResetArgs resetArgs;
2666 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
2667 ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
2668 ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
2669
2670 // Metadata.
2671 ASSERT_TRUE(mDevice->isIgnored());
2672 ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mDevice->getSources());
2673
2674 InputDeviceInfo info = mDevice->getDeviceInfo();
2675 ASSERT_EQ(DEVICE_ID, info.getId());
2676 ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.c_str());
2677 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NONE, info.getKeyboardType());
2678 ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, info.getSources());
2679
2680 // State queries.
2681 ASSERT_EQ(0, mDevice->getMetaState());
2682
2683 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, 0))
2684 << "Ignored device should return unknown key code state.";
2685 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 0))
2686 << "Ignored device should return unknown scan code state.";
2687 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 0))
2688 << "Ignored device should return unknown switch state.";
2689
2690 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B};
2691 uint8_t flags[2] = { 0, 1 };
2692 ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, keyCodes, flags))
2693 << "Ignored device should never mark any key codes.";
2694 ASSERT_EQ(0, flags[0]) << "Flag for unsupported key should be unchanged.";
2695 ASSERT_EQ(1, flags[1]) << "Flag for unsupported key should be unchanged.";
2696}
2697
2698TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRequestsToMappers) {
2699 // Configuration.
2700 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "key", "value");
2701
2702 FakeInputMapper& mapper1 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00002703 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2704 AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002705 mapper1.setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC);
2706 mapper1.setMetaState(AMETA_ALT_ON);
2707 mapper1.addSupportedKeyCode(AKEYCODE_A);
2708 mapper1.addSupportedKeyCode(AKEYCODE_B);
2709 mapper1.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
2710 mapper1.setKeyCodeState(AKEYCODE_B, AKEY_STATE_UP);
2711 mapper1.setScanCodeState(2, AKEY_STATE_DOWN);
2712 mapper1.setScanCodeState(3, AKEY_STATE_UP);
2713 mapper1.setSwitchState(4, AKEY_STATE_DOWN);
2714
2715 FakeInputMapper& mapper2 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00002716 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2717 AINPUT_SOURCE_TOUCHSCREEN);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002718 mapper2.setMetaState(AMETA_SHIFT_ON);
2719
2720 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002721 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002722
Harry Cuttsf13161a2023-03-08 14:15:49 +00002723 std::optional<std::string> propertyValue = mDevice->getConfiguration().getString("key");
2724 ASSERT_TRUE(propertyValue.has_value())
Michael Wrightd02c5b62014-02-10 15:10:22 -08002725 << "Device should have read configuration during configuration phase.";
Harry Cuttsf13161a2023-03-08 14:15:49 +00002726 ASSERT_EQ("value", *propertyValue);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002727
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002728 ASSERT_NO_FATAL_FAILURE(mapper1.assertConfigureWasCalled());
2729 ASSERT_NO_FATAL_FAILURE(mapper2.assertConfigureWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002730
2731 // Reset
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002732 unused += mDevice->reset(ARBITRARY_TIME);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002733 ASSERT_NO_FATAL_FAILURE(mapper1.assertResetWasCalled());
2734 ASSERT_NO_FATAL_FAILURE(mapper2.assertResetWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002735
2736 NotifyDeviceResetArgs resetArgs;
2737 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
2738 ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
2739 ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
2740
2741 // Metadata.
2742 ASSERT_FALSE(mDevice->isIgnored());
2743 ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), mDevice->getSources());
2744
Siarhei Vishniakou1983a712021-06-04 19:27:09 +00002745 InputDeviceInfo info = mDevice->getDeviceInfo();
Michael Wrightd02c5b62014-02-10 15:10:22 -08002746 ASSERT_EQ(DEVICE_ID, info.getId());
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002747 ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002748 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, info.getKeyboardType());
2749 ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), info.getSources());
2750
2751 // State queries.
2752 ASSERT_EQ(AMETA_ALT_ON | AMETA_SHIFT_ON, mDevice->getMetaState())
2753 << "Should query mappers and combine meta states.";
2754
2755 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2756 << "Should return unknown key code state when source not supported.";
2757 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2758 << "Should return unknown scan code state when source not supported.";
2759 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2760 << "Should return unknown switch state when source not supported.";
2761
2762 ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, AKEYCODE_A))
2763 << "Should query mapper when source is supported.";
2764 ASSERT_EQ(AKEY_STATE_UP, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 3))
2765 << "Should query mapper when source is supported.";
2766 ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 4))
2767 << "Should query mapper when source is supported.";
2768
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002769 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2};
Michael Wrightd02c5b62014-02-10 15:10:22 -08002770 uint8_t flags[4] = { 0, 0, 0, 1 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002771 ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -08002772 << "Should do nothing when source is unsupported.";
2773 ASSERT_EQ(0, flags[0]) << "Flag should be unchanged when source is unsupported.";
2774 ASSERT_EQ(0, flags[1]) << "Flag should be unchanged when source is unsupported.";
2775 ASSERT_EQ(0, flags[2]) << "Flag should be unchanged when source is unsupported.";
2776 ASSERT_EQ(1, flags[3]) << "Flag should be unchanged when source is unsupported.";
2777
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002778 ASSERT_TRUE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -08002779 << "Should query mapper when source is supported.";
2780 ASSERT_EQ(1, flags[0]) << "Flag for supported key should be set.";
2781 ASSERT_EQ(1, flags[1]) << "Flag for supported key should be set.";
2782 ASSERT_EQ(0, flags[2]) << "Flag for unsupported key should be unchanged.";
2783 ASSERT_EQ(1, flags[3]) << "Flag for unsupported key should be unchanged.";
2784
2785 // Event handling.
2786 RawEvent event;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002787 event.deviceId = EVENTHUB_ID;
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002788 unused += mDevice->process(&event, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002789
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002790 ASSERT_NO_FATAL_FAILURE(mapper1.assertProcessWasCalled());
2791 ASSERT_NO_FATAL_FAILURE(mapper2.assertProcessWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002792}
2793
Yeabkal Wubshitb1b96db2024-01-24 12:47:00 -08002794TEST_F(InputDeviceTest, Configure_SmoothScrollViewBehaviorNotSet) {
2795 // Set some behavior to force the configuration to be update.
2796 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "1");
2797 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2798 AINPUT_SOURCE_KEYBOARD);
2799
2800 std::list<NotifyArgs> unused =
2801 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2802 /*changes=*/{});
2803
2804 ASSERT_FALSE(mDevice->getDeviceInfo().getViewBehavior().shouldSmoothScroll.has_value());
2805}
2806
2807TEST_F(InputDeviceTest, Configure_SmoothScrollViewBehaviorEnabled) {
2808 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.viewBehavior_smoothScroll", "1");
2809 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2810 AINPUT_SOURCE_KEYBOARD);
2811
2812 std::list<NotifyArgs> unused =
2813 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2814 /*changes=*/{});
2815
2816 ASSERT_TRUE(mDevice->getDeviceInfo().getViewBehavior().shouldSmoothScroll.value_or(false));
2817}
2818
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -07002819TEST_F(InputDeviceTest, WakeDevice_AddsWakeFlagToProcessNotifyArgs) {
2820 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "1");
2821 FakeInputMapper& mapper =
2822 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2823 AINPUT_SOURCE_KEYBOARD);
2824 NotifyMotionArgs args1;
2825 NotifySwitchArgs args2;
2826 NotifyKeyArgs args3;
2827 mapper.setProcessResult({args1, args2, args3});
2828
2829 InputReaderConfiguration config;
2830 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2831
2832 RawEvent event;
2833 event.deviceId = EVENTHUB_ID;
2834 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2835
2836 for (auto& arg : notifyArgs) {
2837 if (const auto notifyMotionArgs = std::get_if<NotifyMotionArgs>(&arg)) {
2838 ASSERT_EQ(POLICY_FLAG_WAKE, notifyMotionArgs->policyFlags);
2839 } else if (const auto notifySwitchArgs = std::get_if<NotifySwitchArgs>(&arg)) {
2840 ASSERT_EQ(POLICY_FLAG_WAKE, notifySwitchArgs->policyFlags);
2841 } else if (const auto notifyKeyArgs = std::get_if<NotifyKeyArgs>(&arg)) {
2842 ASSERT_EQ(POLICY_FLAG_WAKE, notifyKeyArgs->policyFlags);
2843 }
2844 }
2845}
2846
2847TEST_F(InputDeviceTest, NotWakeDevice_DoesNotAddWakeFlagToProcessNotifyArgs) {
2848 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "0");
2849 FakeInputMapper& mapper =
2850 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2851 AINPUT_SOURCE_KEYBOARD);
2852 NotifyMotionArgs args;
2853 mapper.setProcessResult({args});
2854
2855 InputReaderConfiguration config;
2856 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2857
2858 RawEvent event;
2859 event.deviceId = EVENTHUB_ID;
2860 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2861
2862 // POLICY_FLAG_WAKE is not added to the NotifyArgs.
2863 ASSERT_EQ(0u, std::get<NotifyMotionArgs>(notifyArgs.front()).policyFlags);
2864}
2865
2866TEST_F(InputDeviceTest, NotWakeDevice_DoesNotRemoveExistingWakeFlagFromProcessNotifyArgs) {
2867 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "0");
2868 FakeInputMapper& mapper =
2869 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2870 AINPUT_SOURCE_KEYBOARD);
2871 NotifyMotionArgs args;
2872 args.policyFlags = POLICY_FLAG_WAKE;
2873 mapper.setProcessResult({args});
2874
2875 InputReaderConfiguration config;
2876 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2877
2878 RawEvent event;
2879 event.deviceId = EVENTHUB_ID;
2880 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2881
2882 // The POLICY_FLAG_WAKE is preserved, despite the device being a non-wake device.
2883 ASSERT_EQ(POLICY_FLAG_WAKE, std::get<NotifyMotionArgs>(notifyArgs.front()).policyFlags);
2884}
2885
Arthur Hung2c9a3342019-07-23 14:18:59 +08002886// A single input device is associated with a specific display. Check that:
2887// 1. Device is disabled if the viewport corresponding to the associated display is not found
Arpit Singh48189772023-05-30 14:12:49 +00002888// 2. Device is disabled when configure API is called
Arthur Hung2c9a3342019-07-23 14:18:59 +08002889TEST_F(InputDeviceTest, Configure_AssignsDisplayPort) {
Arpit Singh8e6fb252023-04-06 11:49:17 +00002890 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2891 AINPUT_SOURCE_TOUCHSCREEN);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002892
2893 // First Configuration.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002894 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002895 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2896 /*changes=*/{});
Arthur Hung2c9a3342019-07-23 14:18:59 +08002897
2898 // Device should be enabled by default.
2899 ASSERT_TRUE(mDevice->isEnabled());
2900
2901 // Prepare associated info.
2902 constexpr uint8_t hdmi = 1;
2903 const std::string UNIQUE_ID = "local:1";
2904
2905 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002906 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002907 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002908 // Device should be disabled because it is associated with a specific display via
2909 // input port <-> display port association, but the corresponding display is not found
2910 ASSERT_FALSE(mDevice->isEnabled());
2911
2912 // Prepare displays.
2913 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +00002914 ui::ROTATION_0, /*isActive=*/true, UNIQUE_ID, hdmi,
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00002915 ViewportType::INTERNAL);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002916 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002917 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002918 ASSERT_TRUE(mDevice->isEnabled());
2919
2920 // Device should be disabled after set disable.
2921 mFakePolicy->addDisabledDevice(mDevice->getId());
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002922 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002923 InputReaderConfiguration::Change::ENABLED_STATE);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002924 ASSERT_FALSE(mDevice->isEnabled());
2925
2926 // Device should still be disabled even found the associated display.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002927 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002928 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002929 ASSERT_FALSE(mDevice->isEnabled());
2930}
Michael Wrightd02c5b62014-02-10 15:10:22 -08002931
Christine Franks1ba71cc2021-04-07 14:37:42 -07002932TEST_F(InputDeviceTest, Configure_AssignsDisplayUniqueId) {
2933 // Device should be enabled by default.
2934 mFakePolicy->clearViewports();
Arpit Singh8e6fb252023-04-06 11:49:17 +00002935 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2936 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002937 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002938 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2939 /*changes=*/{});
Christine Franks1ba71cc2021-04-07 14:37:42 -07002940 ASSERT_TRUE(mDevice->isEnabled());
2941
2942 // Device should be disabled because it is associated with a specific display, but the
2943 // corresponding display is not found.
Christine Franks2a2293c2022-01-18 11:51:16 -08002944 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002945 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002946 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002947 ASSERT_FALSE(mDevice->isEnabled());
2948
2949 // Device should be enabled when a display is found.
2950 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00002951 ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
Christine Franks1ba71cc2021-04-07 14:37:42 -07002952 NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002953 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002954 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002955 ASSERT_TRUE(mDevice->isEnabled());
2956
2957 // Device should be disabled after set disable.
2958 mFakePolicy->addDisabledDevice(mDevice->getId());
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002959 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002960 InputReaderConfiguration::Change::ENABLED_STATE);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002961 ASSERT_FALSE(mDevice->isEnabled());
2962
2963 // Device should still be disabled even found the associated display.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002964 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002965 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002966 ASSERT_FALSE(mDevice->isEnabled());
2967}
2968
Christine Franks2a2293c2022-01-18 11:51:16 -08002969TEST_F(InputDeviceTest, Configure_UniqueId_CorrectlyMatches) {
2970 mFakePolicy->clearViewports();
Arpit Singh8e6fb252023-04-06 11:49:17 +00002971 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2972 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002973 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002974 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2975 /*changes=*/{});
Christine Franks2a2293c2022-01-18 11:51:16 -08002976
Christine Franks2a2293c2022-01-18 11:51:16 -08002977 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
2978 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00002979 ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
Christine Franks2a2293c2022-01-18 11:51:16 -08002980 NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan55c5ee22024-02-14 06:03:02 +00002981 const auto initialGeneration = mDevice->getGeneration();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002982 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002983 InputReaderConfiguration::Change::DISPLAY_INFO);
Antonio Kantek0ac5e092024-04-22 17:10:27 +00002984 ASSERT_EQ(DISPLAY_UNIQUE_ID, mDevice->getAssociatedDisplayUniqueIdByPort());
Prabir Pradhan55c5ee22024-02-14 06:03:02 +00002985 ASSERT_GT(mDevice->getGeneration(), initialGeneration);
2986 ASSERT_EQ(mDevice->getDeviceInfo().getAssociatedDisplayId(), SECONDARY_DISPLAY_ID);
Christine Franks2a2293c2022-01-18 11:51:16 -08002987}
2988
Siarhei Vishniakou30feb8c2022-09-28 10:48:29 -07002989/**
2990 * This test reproduces a crash caused by a dangling reference that remains after device is added
2991 * and removed. The reference is accessed in InputDevice::dump(..);
2992 */
2993TEST_F(InputDeviceTest, DumpDoesNotCrash) {
2994 constexpr int32_t TEST_EVENTHUB_ID = 10;
2995 mFakeEventHub->addDevice(TEST_EVENTHUB_ID, "Test EventHub device", InputDeviceClass::BATTERY);
2996
Harry Cutts33476232023-01-30 19:57:29 +00002997 InputDevice device(mReader->getContext(), /*id=*/1, /*generation=*/2, /*identifier=*/{});
Arpit Singh82f29a12023-06-13 15:05:53 +00002998 auto _ = device.addEventHubDevice(ARBITRARY_TIME, TEST_EVENTHUB_ID,
2999 mFakePolicy->getReaderConfiguration());
Siarhei Vishniakou30feb8c2022-09-28 10:48:29 -07003000 device.removeEventHubDevice(TEST_EVENTHUB_ID);
3001 std::string dumpStr, eventHubDevStr;
3002 device.dump(dumpStr, eventHubDevStr);
3003}
3004
Prabir Pradhanb54ffb22022-10-27 18:03:34 +00003005TEST_F(InputDeviceTest, GetBluetoothAddress) {
3006 const auto& address = mReader->getBluetoothAddress(DEVICE_ID);
3007 ASSERT_TRUE(address);
3008 ASSERT_EQ(DEVICE_BLUETOOTH_ADDRESS, *address);
3009}
3010
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003011TEST_F(InputDeviceTest, KernelBufferOverflowResetsMappers) {
3012 mFakePolicy->clearViewports();
3013 FakeInputMapper& mapper =
3014 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
3015 AINPUT_SOURCE_KEYBOARD);
3016 std::list<NotifyArgs> unused =
3017 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
3018 /*changes=*/{});
3019
3020 mapper.assertConfigureWasCalled();
3021 mapper.assertResetWasNotCalled();
3022
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -08003023 RawEvent event{.when = ARBITRARY_TIME,
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003024 .readTime = ARBITRARY_TIME,
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -08003025 .deviceId = EVENTHUB_ID,
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003026 .type = EV_SYN,
3027 .code = SYN_REPORT,
3028 .value = 0};
3029
3030 // Events are processed normally.
3031 unused = mDevice->process(&event, /*count=*/1);
3032 mapper.assertProcessWasCalled();
3033
3034 // Simulate a kernel buffer overflow, which generates a SYN_DROPPED event.
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003035 event.type = EV_SYN;
3036 event.code = SYN_DROPPED;
3037 event.value = 0;
3038 unused = mDevice->process(&event, /*count=*/1);
3039 mapper.assertProcessWasNotCalled();
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003040
3041 // All events until the next SYN_REPORT should be dropped.
3042 event.type = EV_KEY;
3043 event.code = KEY_A;
3044 event.value = 1;
3045 unused = mDevice->process(&event, /*count=*/1);
3046 mapper.assertProcessWasNotCalled();
3047
3048 // We get the SYN_REPORT event now, which is not forwarded to mappers.
Arpit Singh4b4a4572023-11-24 18:19:56 +00003049 // This should reset the mapper.
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003050 event.type = EV_SYN;
3051 event.code = SYN_REPORT;
3052 event.value = 0;
3053 unused = mDevice->process(&event, /*count=*/1);
3054 mapper.assertProcessWasNotCalled();
Arpit Singh4b4a4572023-11-24 18:19:56 +00003055 mapper.assertResetWasCalled();
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003056
3057 // The mapper receives events normally now.
3058 event.type = EV_KEY;
3059 event.code = KEY_B;
3060 event.value = 1;
3061 unused = mDevice->process(&event, /*count=*/1);
3062 mapper.assertProcessWasCalled();
3063}
3064
Michael Wrightd02c5b62014-02-10 15:10:22 -08003065// --- SwitchInputMapperTest ---
3066
3067class SwitchInputMapperTest : public InputMapperTest {
3068protected:
3069};
3070
3071TEST_F(SwitchInputMapperTest, GetSources) {
Arpit Singhdf992eb2023-04-26 16:12:10 +00003072 SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08003073
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003074 ASSERT_EQ(uint32_t(AINPUT_SOURCE_SWITCH), mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003075}
3076
3077TEST_F(SwitchInputMapperTest, GetSwitchState) {
Arpit Singhdf992eb2023-04-26 16:12:10 +00003078 SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08003079
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003080 mFakeEventHub->setSwitchState(EVENTHUB_ID, SW_LID, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003081 ASSERT_EQ(1, mapper.getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003082
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003083 mFakeEventHub->setSwitchState(EVENTHUB_ID, SW_LID, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003084 ASSERT_EQ(0, mapper.getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003085}
3086
3087TEST_F(SwitchInputMapperTest, Process) {
Arpit Singhdf992eb2023-04-26 16:12:10 +00003088 SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003089 std::list<NotifyArgs> out;
3090 out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SW, SW_LID, 1);
3091 ASSERT_TRUE(out.empty());
3092 out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SW, SW_JACK_PHYSICAL_INSERT, 1);
3093 ASSERT_TRUE(out.empty());
3094 out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SW, SW_HEADPHONE_INSERT, 0);
3095 ASSERT_TRUE(out.empty());
3096 out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003097
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003098 ASSERT_EQ(1u, out.size());
3099 const NotifySwitchArgs& args = std::get<NotifySwitchArgs>(*out.begin());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003100 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
Dan Albert1bd2fc02016-02-02 15:11:57 -08003101 ASSERT_EQ((1U << SW_LID) | (1U << SW_JACK_PHYSICAL_INSERT), args.switchValues);
3102 ASSERT_EQ((1U << SW_LID) | (1U << SW_JACK_PHYSICAL_INSERT) | (1 << SW_HEADPHONE_INSERT),
Michael Wrightd02c5b62014-02-10 15:10:22 -08003103 args.switchMask);
3104 ASSERT_EQ(uint32_t(0), args.policyFlags);
3105}
3106
Chris Ye87143712020-11-10 05:05:58 +00003107// --- VibratorInputMapperTest ---
3108class VibratorInputMapperTest : public InputMapperTest {
3109protected:
3110 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::VIBRATOR); }
3111};
3112
3113TEST_F(VibratorInputMapperTest, GetSources) {
Arpit Singh0f26b302023-04-26 16:23:13 +00003114 VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
Chris Ye87143712020-11-10 05:05:58 +00003115
3116 ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mapper.getSources());
3117}
3118
3119TEST_F(VibratorInputMapperTest, GetVibratorIds) {
Arpit Singh0f26b302023-04-26 16:23:13 +00003120 VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
Chris Ye87143712020-11-10 05:05:58 +00003121
3122 ASSERT_EQ(mapper.getVibratorIds().size(), 2U);
3123}
3124
3125TEST_F(VibratorInputMapperTest, Vibrate) {
3126 constexpr uint8_t DEFAULT_AMPLITUDE = 192;
Chris Yefb552902021-02-03 17:18:37 -08003127 constexpr int32_t VIBRATION_TOKEN = 100;
Arpit Singh0f26b302023-04-26 16:23:13 +00003128 VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
Chris Ye87143712020-11-10 05:05:58 +00003129
3130 VibrationElement pattern(2);
3131 VibrationSequence sequence(2);
3132 pattern.duration = std::chrono::milliseconds(200);
Harry Cutts33476232023-01-30 19:57:29 +00003133 pattern.channels = {{/*vibratorId=*/0, DEFAULT_AMPLITUDE / 2},
3134 {/*vibratorId=*/1, DEFAULT_AMPLITUDE}};
Chris Ye87143712020-11-10 05:05:58 +00003135 sequence.addElement(pattern);
3136 pattern.duration = std::chrono::milliseconds(500);
Harry Cutts33476232023-01-30 19:57:29 +00003137 pattern.channels = {{/*vibratorId=*/0, DEFAULT_AMPLITUDE / 4},
3138 {/*vibratorId=*/1, DEFAULT_AMPLITUDE}};
Chris Ye87143712020-11-10 05:05:58 +00003139 sequence.addElement(pattern);
3140
3141 std::vector<int64_t> timings = {0, 1};
3142 std::vector<uint8_t> amplitudes = {DEFAULT_AMPLITUDE, DEFAULT_AMPLITUDE / 2};
3143
3144 ASSERT_FALSE(mapper.isVibrating());
Chris Yefb552902021-02-03 17:18:37 -08003145 // Start vibrating
Harry Cutts33476232023-01-30 19:57:29 +00003146 std::list<NotifyArgs> out = mapper.vibrate(sequence, /*repeat=*/-1, VIBRATION_TOKEN);
Chris Ye87143712020-11-10 05:05:58 +00003147 ASSERT_TRUE(mapper.isVibrating());
Chris Yefb552902021-02-03 17:18:37 -08003148 // Verify vibrator state listener was notified.
3149 mReader->loopOnce();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003150 ASSERT_EQ(1u, out.size());
3151 const NotifyVibratorStateArgs& vibrateArgs = std::get<NotifyVibratorStateArgs>(*out.begin());
3152 ASSERT_EQ(DEVICE_ID, vibrateArgs.deviceId);
3153 ASSERT_TRUE(vibrateArgs.isOn);
Chris Yefb552902021-02-03 17:18:37 -08003154 // Stop vibrating
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003155 out = mapper.cancelVibrate(VIBRATION_TOKEN);
Chris Yefb552902021-02-03 17:18:37 -08003156 ASSERT_FALSE(mapper.isVibrating());
3157 // Verify vibrator state listener was notified.
3158 mReader->loopOnce();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003159 ASSERT_EQ(1u, out.size());
3160 const NotifyVibratorStateArgs& cancelArgs = std::get<NotifyVibratorStateArgs>(*out.begin());
3161 ASSERT_EQ(DEVICE_ID, cancelArgs.deviceId);
3162 ASSERT_FALSE(cancelArgs.isOn);
Chris Ye87143712020-11-10 05:05:58 +00003163}
Michael Wrightd02c5b62014-02-10 15:10:22 -08003164
Chris Yef59a2f42020-10-16 12:55:26 -07003165// --- SensorInputMapperTest ---
3166
3167class SensorInputMapperTest : public InputMapperTest {
3168protected:
3169 static const int32_t ACCEL_RAW_MIN;
3170 static const int32_t ACCEL_RAW_MAX;
3171 static const int32_t ACCEL_RAW_FUZZ;
3172 static const int32_t ACCEL_RAW_FLAT;
3173 static const int32_t ACCEL_RAW_RESOLUTION;
3174
3175 static const int32_t GYRO_RAW_MIN;
3176 static const int32_t GYRO_RAW_MAX;
3177 static const int32_t GYRO_RAW_FUZZ;
3178 static const int32_t GYRO_RAW_FLAT;
3179 static const int32_t GYRO_RAW_RESOLUTION;
3180
3181 static const float GRAVITY_MS2_UNIT;
3182 static const float DEGREE_RADIAN_UNIT;
3183
3184 void prepareAccelAxes();
3185 void prepareGyroAxes();
3186 void setAccelProperties();
3187 void setGyroProperties();
3188 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::SENSOR); }
3189};
3190
3191const int32_t SensorInputMapperTest::ACCEL_RAW_MIN = -32768;
3192const int32_t SensorInputMapperTest::ACCEL_RAW_MAX = 32768;
3193const int32_t SensorInputMapperTest::ACCEL_RAW_FUZZ = 16;
3194const int32_t SensorInputMapperTest::ACCEL_RAW_FLAT = 0;
3195const int32_t SensorInputMapperTest::ACCEL_RAW_RESOLUTION = 8192;
3196
3197const int32_t SensorInputMapperTest::GYRO_RAW_MIN = -2097152;
3198const int32_t SensorInputMapperTest::GYRO_RAW_MAX = 2097152;
3199const int32_t SensorInputMapperTest::GYRO_RAW_FUZZ = 16;
3200const int32_t SensorInputMapperTest::GYRO_RAW_FLAT = 0;
3201const int32_t SensorInputMapperTest::GYRO_RAW_RESOLUTION = 1024;
3202
3203const float SensorInputMapperTest::GRAVITY_MS2_UNIT = 9.80665f;
3204const float SensorInputMapperTest::DEGREE_RADIAN_UNIT = 0.0174533f;
3205
3206void SensorInputMapperTest::prepareAccelAxes() {
3207 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3208 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3209 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3210 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3211 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Z, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3212 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3213}
3214
3215void SensorInputMapperTest::prepareGyroAxes() {
3216 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RX, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3217 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3218 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RY, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3219 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3220 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RZ, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3221 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3222}
3223
3224void SensorInputMapperTest::setAccelProperties() {
3225 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 0, InputDeviceSensorType::ACCELEROMETER,
3226 /* sensorDataIndex */ 0);
3227 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 1, InputDeviceSensorType::ACCELEROMETER,
3228 /* sensorDataIndex */ 1);
3229 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 2, InputDeviceSensorType::ACCELEROMETER,
3230 /* sensorDataIndex */ 2);
3231 mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP);
3232 addConfigurationProperty("sensor.accelerometer.reportingMode", "0");
3233 addConfigurationProperty("sensor.accelerometer.maxDelay", "100000");
3234 addConfigurationProperty("sensor.accelerometer.minDelay", "5000");
3235 addConfigurationProperty("sensor.accelerometer.power", "1.5");
3236}
3237
3238void SensorInputMapperTest::setGyroProperties() {
3239 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 3, InputDeviceSensorType::GYROSCOPE,
3240 /* sensorDataIndex */ 0);
3241 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 4, InputDeviceSensorType::GYROSCOPE,
3242 /* sensorDataIndex */ 1);
3243 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 5, InputDeviceSensorType::GYROSCOPE,
3244 /* sensorDataIndex */ 2);
3245 mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP);
3246 addConfigurationProperty("sensor.gyroscope.reportingMode", "0");
3247 addConfigurationProperty("sensor.gyroscope.maxDelay", "100000");
3248 addConfigurationProperty("sensor.gyroscope.minDelay", "5000");
3249 addConfigurationProperty("sensor.gyroscope.power", "0.8");
3250}
3251
3252TEST_F(SensorInputMapperTest, GetSources) {
Arpit Singhfb706c32023-04-26 15:07:55 +00003253 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003254
3255 ASSERT_EQ(static_cast<uint32_t>(AINPUT_SOURCE_SENSOR), mapper.getSources());
3256}
3257
3258TEST_F(SensorInputMapperTest, ProcessAccelerometerSensor) {
3259 setAccelProperties();
3260 prepareAccelAxes();
Arpit Singhfb706c32023-04-26 15:07:55 +00003261 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003262
3263 ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::ACCELEROMETER,
3264 std::chrono::microseconds(10000),
3265 std::chrono::microseconds(0)));
Chris Yee14523a2020-12-19 13:46:00 -08003266 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003267 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, 20000);
3268 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, -20000);
3269 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Z, 40000);
3270 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000);
3271 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Chris Yef59a2f42020-10-16 12:55:26 -07003272
3273 NotifySensorArgs args;
3274 std::vector<float> values = {20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT,
3275 -20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT,
3276 40000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT};
3277
3278 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args));
3279 ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR);
3280 ASSERT_EQ(args.deviceId, DEVICE_ID);
3281 ASSERT_EQ(args.sensorType, InputDeviceSensorType::ACCELEROMETER);
3282 ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH);
3283 ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME);
3284 ASSERT_EQ(args.values, values);
3285 mapper.flushSensor(InputDeviceSensorType::ACCELEROMETER);
3286}
3287
3288TEST_F(SensorInputMapperTest, ProcessGyroscopeSensor) {
3289 setGyroProperties();
3290 prepareGyroAxes();
Arpit Singhfb706c32023-04-26 15:07:55 +00003291 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003292
3293 ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::GYROSCOPE,
3294 std::chrono::microseconds(10000),
3295 std::chrono::microseconds(0)));
Chris Yee14523a2020-12-19 13:46:00 -08003296 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003297 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RX, 20000);
3298 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RY, -20000);
3299 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RZ, 40000);
3300 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000);
3301 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Chris Yef59a2f42020-10-16 12:55:26 -07003302
3303 NotifySensorArgs args;
3304 std::vector<float> values = {20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT,
3305 -20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT,
3306 40000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT};
3307
3308 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args));
3309 ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR);
3310 ASSERT_EQ(args.deviceId, DEVICE_ID);
3311 ASSERT_EQ(args.sensorType, InputDeviceSensorType::GYROSCOPE);
3312 ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH);
3313 ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME);
3314 ASSERT_EQ(args.values, values);
3315 mapper.flushSensor(InputDeviceSensorType::GYROSCOPE);
3316}
3317
Michael Wrightd02c5b62014-02-10 15:10:22 -08003318// --- KeyboardInputMapperTest ---
3319
3320class KeyboardInputMapperTest : public InputMapperTest {
3321protected:
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003322 void SetUp() override {
3323 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
3324 InputDeviceClass::ALPHAKEY);
3325 }
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003326 const std::string UNIQUE_ID = "local:0";
Zixuan Qufecb6062022-11-12 04:44:31 +00003327 const KeyboardLayoutInfo DEVICE_KEYBOARD_LAYOUT_INFO = KeyboardLayoutInfo("en-US", "qwerty");
Michael Wrighta9cf4192022-12-01 23:46:39 +00003328 void prepareDisplay(ui::Rotation orientation);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003329
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003330 void testDPadKeyRotation(KeyboardInputMapper& mapper, int32_t originalScanCode,
Arthur Hung2c9a3342019-07-23 14:18:59 +08003331 int32_t originalKeyCode, int32_t rotatedKeyCode,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003332 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003333};
3334
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003335/* Similar to setDisplayInfoAndReconfigure, but pre-populates all parameters except for the
3336 * orientation.
3337 */
Michael Wrighta9cf4192022-12-01 23:46:39 +00003338void KeyboardInputMapperTest::prepareDisplay(ui::Rotation orientation) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003339 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
3340 NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003341}
3342
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003343void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper& mapper,
Arthur Hung2c9a3342019-07-23 14:18:59 +08003344 int32_t originalScanCode, int32_t originalKeyCode,
Linnan Li13bf76a2024-05-05 19:18:02 +08003345 int32_t rotatedKeyCode,
3346 ui::LogicalDisplayId displayId) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003347 NotifyKeyArgs args;
3348
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003349 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003350 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3351 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3352 ASSERT_EQ(originalScanCode, args.scanCode);
3353 ASSERT_EQ(rotatedKeyCode, args.keyCode);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003354 ASSERT_EQ(displayId, args.displayId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003355
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003356 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003357 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3358 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3359 ASSERT_EQ(originalScanCode, args.scanCode);
3360 ASSERT_EQ(rotatedKeyCode, args.keyCode);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003361 ASSERT_EQ(displayId, args.displayId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003362}
3363
Michael Wrightd02c5b62014-02-10 15:10:22 -08003364TEST_F(KeyboardInputMapperTest, GetSources) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003365 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003366 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003367
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003368 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003369}
3370
3371TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) {
3372 const int32_t USAGE_A = 0x070004;
3373 const int32_t USAGE_UNKNOWN = 0x07ffff;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003374 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3375 mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
Chris Yea52ade12020-08-27 16:49:20 -07003376 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, POLICY_FLAG_WAKE);
3377 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, POLICY_FLAG_WAKE);
3378 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, POLICY_FLAG_WAKE);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003379
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003380 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003381 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003382 // Initial metastate is AMETA_NONE.
3383 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003384
3385 // Key down by scan code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003386 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003387 NotifyKeyArgs args;
3388 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3389 ASSERT_EQ(DEVICE_ID, args.deviceId);
3390 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3391 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3392 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3393 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3394 ASSERT_EQ(KEY_HOME, args.scanCode);
3395 ASSERT_EQ(AMETA_NONE, args.metaState);
3396 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3397 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3398 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3399
3400 // Key up by scan code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003401 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003402 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3403 ASSERT_EQ(DEVICE_ID, args.deviceId);
3404 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3405 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3406 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3407 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3408 ASSERT_EQ(KEY_HOME, args.scanCode);
3409 ASSERT_EQ(AMETA_NONE, args.metaState);
3410 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3411 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3412 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3413
3414 // Key down by usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003415 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A);
3416 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, 0, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003417 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3418 ASSERT_EQ(DEVICE_ID, args.deviceId);
3419 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3420 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3421 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3422 ASSERT_EQ(AKEYCODE_A, args.keyCode);
3423 ASSERT_EQ(0, args.scanCode);
3424 ASSERT_EQ(AMETA_NONE, args.metaState);
3425 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3426 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3427 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3428
3429 // Key up by usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003430 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A);
3431 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003432 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3433 ASSERT_EQ(DEVICE_ID, args.deviceId);
3434 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3435 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3436 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3437 ASSERT_EQ(AKEYCODE_A, args.keyCode);
3438 ASSERT_EQ(0, args.scanCode);
3439 ASSERT_EQ(AMETA_NONE, args.metaState);
3440 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3441 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3442 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3443
3444 // Key down with unknown scan code or usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003445 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
3446 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003447 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3448 ASSERT_EQ(DEVICE_ID, args.deviceId);
3449 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3450 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3451 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3452 ASSERT_EQ(0, args.keyCode);
3453 ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
3454 ASSERT_EQ(AMETA_NONE, args.metaState);
3455 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3456 ASSERT_EQ(0U, args.policyFlags);
3457 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3458
3459 // Key up with unknown scan code or usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003460 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
3461 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_UNKNOWN, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003462 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3463 ASSERT_EQ(DEVICE_ID, args.deviceId);
3464 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3465 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3466 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3467 ASSERT_EQ(0, args.keyCode);
3468 ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
3469 ASSERT_EQ(AMETA_NONE, args.metaState);
3470 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3471 ASSERT_EQ(0U, args.policyFlags);
3472 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3473}
3474
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003475TEST_F(KeyboardInputMapperTest, Process_KeyRemapping) {
3476 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
3477 mFakeEventHub->addKey(EVENTHUB_ID, KEY_B, 0, AKEYCODE_B, 0);
3478 mFakeEventHub->addKeyRemapping(EVENTHUB_ID, AKEYCODE_A, AKEYCODE_B);
3479
3480 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003481 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003482
3483 // Key down by scan code.
3484 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_A, 1);
3485 NotifyKeyArgs args;
3486 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3487 ASSERT_EQ(AKEYCODE_B, args.keyCode);
3488
3489 // Key up by scan code.
3490 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 0);
3491 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3492 ASSERT_EQ(AKEYCODE_B, args.keyCode);
3493}
3494
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003495/**
3496 * Ensure that the readTime is set to the time when the EV_KEY is received.
3497 */
3498TEST_F(KeyboardInputMapperTest, Process_SendsReadTime) {
3499 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3500
3501 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003502 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003503 NotifyKeyArgs args;
3504
3505 // Key down
Harry Cutts33476232023-01-30 19:57:29 +00003506 process(mapper, ARBITRARY_TIME, /*readTime=*/12, EV_KEY, KEY_HOME, 1);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003507 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3508 ASSERT_EQ(12, args.readTime);
3509
3510 // Key up
Harry Cutts33476232023-01-30 19:57:29 +00003511 process(mapper, ARBITRARY_TIME, /*readTime=*/15, EV_KEY, KEY_HOME, 1);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003512 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3513 ASSERT_EQ(15, args.readTime);
3514}
3515
Michael Wrightd02c5b62014-02-10 15:10:22 -08003516TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003517 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFTSHIFT, 0, AKEYCODE_SHIFT_LEFT, 0);
3518 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
Chris Yea52ade12020-08-27 16:49:20 -07003519 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 0);
3520 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0);
3521 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003522
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003523 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003524 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003525
Arthur Hung95f68612022-04-07 14:08:22 +08003526 // Initial metastate is AMETA_NONE.
3527 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003528
3529 // Metakey down.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003530 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003531 NotifyKeyArgs args;
3532 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3533 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003534 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
arthurhungdcef2dc2020-08-11 14:47:50 +08003535 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003536
3537 // Key down.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003538 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003539 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3540 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003541 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003542
3543 // Key up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003544 process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_KEY, KEY_A, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003545 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3546 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003547 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003548
3549 // Metakey up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003550 process(mapper, ARBITRARY_TIME + 3, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003551 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3552 ASSERT_EQ(AMETA_NONE, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003553 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
arthurhungdcef2dc2020-08-11 14:47:50 +08003554 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003555}
3556
3557TEST_F(KeyboardInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateDPad) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003558 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3559 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3560 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3561 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003562
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003563 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003564 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003565
Michael Wrighta9cf4192022-12-01 23:46:39 +00003566 prepareDisplay(ui::ROTATION_90);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003567 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3568 KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
3569 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3570 KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
3571 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3572 KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
3573 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3574 KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
3575}
3576
3577TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003578 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3579 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3580 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3581 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003582
Michael Wrightd02c5b62014-02-10 15:10:22 -08003583 addConfigurationProperty("keyboard.orientationAware", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003584 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003585 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003586
Michael Wrighta9cf4192022-12-01 23:46:39 +00003587 prepareDisplay(ui::ROTATION_0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003588 ASSERT_NO_FATAL_FAILURE(
3589 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
3590 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3591 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3592 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3593 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3594 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3595 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003596
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003597 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003598 prepareDisplay(ui::ROTATION_90);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003599 ASSERT_NO_FATAL_FAILURE(
3600 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3601 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3602 AKEYCODE_DPAD_UP, DISPLAY_ID));
3603 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3604 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3605 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3606 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003607
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003608 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003609 prepareDisplay(ui::ROTATION_180);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003610 ASSERT_NO_FATAL_FAILURE(
3611 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3612 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3613 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3614 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3615 AKEYCODE_DPAD_UP, DISPLAY_ID));
3616 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3617 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003618
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003619 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003620 prepareDisplay(ui::ROTATION_270);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003621 ASSERT_NO_FATAL_FAILURE(
3622 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3623 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3624 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3625 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3626 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3627 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3628 AKEYCODE_DPAD_UP, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003629
3630 // Special case: if orientation changes while key is down, we still emit the same keycode
3631 // in the key up as we did in the key down.
3632 NotifyKeyArgs args;
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003633 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003634 prepareDisplay(ui::ROTATION_270);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003635 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003636 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3637 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3638 ASSERT_EQ(KEY_UP, args.scanCode);
3639 ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
3640
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003641 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003642 prepareDisplay(ui::ROTATION_180);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003643 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003644 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3645 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3646 ASSERT_EQ(KEY_UP, args.scanCode);
3647 ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
3648}
3649
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003650TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_NotOrientationAware) {
3651 // If the keyboard is not orientation aware,
3652 // key events should not be associated with a specific display id
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003653 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003654
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003655 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003656 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003657 NotifyKeyArgs args;
3658
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003659 // Display id should be LogicalDisplayId::INVALID without any display configuration.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003660 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003661 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003662 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003663 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003664 ASSERT_EQ(ui::LogicalDisplayId::INVALID, args.displayId);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003665
Michael Wrighta9cf4192022-12-01 23:46:39 +00003666 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003667 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003668 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003669 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003670 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003671 ASSERT_EQ(ui::LogicalDisplayId::INVALID, args.displayId);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003672}
3673
3674TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_OrientationAware) {
3675 // If the keyboard is orientation aware,
3676 // key events should be associated with the internal viewport
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003677 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003678
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003679 addConfigurationProperty("keyboard.orientationAware", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003680 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003681 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003682 NotifyKeyArgs args;
3683
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003684 // Display id should be LogicalDisplayId::INVALID without any display configuration.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003685 // ^--- already checked by the previous test
3686
Michael Wrighta9cf4192022-12-01 23:46:39 +00003687 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003688 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003689 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003690 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003691 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003692 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3693 ASSERT_EQ(DISPLAY_ID, args.displayId);
3694
Linnan Li13bf76a2024-05-05 19:18:02 +08003695 constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003696 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003697 setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003698 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003699 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003700 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003701 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003702 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3703 ASSERT_EQ(newDisplayId, args.displayId);
3704}
3705
Michael Wrightd02c5b62014-02-10 15:10:22 -08003706TEST_F(KeyboardInputMapperTest, GetKeyCodeState) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003707 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003708 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003709
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003710 mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003711 ASSERT_EQ(1, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003712
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003713 mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003714 ASSERT_EQ(0, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003715}
3716
Philip Junker4af3b3d2021-12-14 10:36:55 +01003717TEST_F(KeyboardInputMapperTest, GetKeyCodeForKeyLocation) {
3718 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003719 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Philip Junker4af3b3d2021-12-14 10:36:55 +01003720
3721 mFakeEventHub->addKeyCodeMapping(EVENTHUB_ID, AKEYCODE_Y, AKEYCODE_Z);
3722 ASSERT_EQ(AKEYCODE_Z, mapper.getKeyCodeForKeyLocation(AKEYCODE_Y))
3723 << "If a mapping is available, the result is equal to the mapping";
3724
3725 ASSERT_EQ(AKEYCODE_A, mapper.getKeyCodeForKeyLocation(AKEYCODE_A))
3726 << "If no mapping is available, the result is the key location";
3727}
3728
Michael Wrightd02c5b62014-02-10 15:10:22 -08003729TEST_F(KeyboardInputMapperTest, GetScanCodeState) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003730 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003731 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003732
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003733 mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003734 ASSERT_EQ(1, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003735
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003736 mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003737 ASSERT_EQ(0, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003738}
3739
3740TEST_F(KeyboardInputMapperTest, MarkSupportedKeyCodes) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003741 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003742 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003743
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003744 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003745
Michael Wrightd02c5b62014-02-10 15:10:22 -08003746 uint8_t flags[2] = { 0, 0 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07003747 ASSERT_TRUE(mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_A, AKEYCODE_B}, flags));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003748 ASSERT_TRUE(flags[0]);
3749 ASSERT_FALSE(flags[1]);
3750}
3751
3752TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003753 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3754 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3755 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3756 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3757 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3758 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003759
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003760 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003761 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003762 // Initial metastate is AMETA_NONE.
3763 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003764
3765 // Initialization should have turned all of the lights off.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003766 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3767 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3768 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003769
3770 // Toggle caps lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003771 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3772 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003773 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3774 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3775 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003776 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003777
3778 // Toggle num lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003779 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3780 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003781 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3782 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3783 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003784 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003785
3786 // Toggle caps lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003787 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3788 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003789 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3790 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3791 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003792 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003793
3794 // Toggle scroll lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003795 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3796 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003797 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3798 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3799 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003800 ASSERT_EQ(AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003801
3802 // Toggle num lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003803 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3804 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003805 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3806 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3807 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003808 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003809
3810 // Toggle scroll lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003811 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3812 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003813 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3814 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3815 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003816 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003817}
3818
Chris Yea52ade12020-08-27 16:49:20 -07003819TEST_F(KeyboardInputMapperTest, NoMetaStateWhenMetaKeysNotPresent) {
3820 mFakeEventHub->addKey(EVENTHUB_ID, BTN_A, 0, AKEYCODE_BUTTON_A, 0);
3821 mFakeEventHub->addKey(EVENTHUB_ID, BTN_B, 0, AKEYCODE_BUTTON_B, 0);
3822 mFakeEventHub->addKey(EVENTHUB_ID, BTN_X, 0, AKEYCODE_BUTTON_X, 0);
3823 mFakeEventHub->addKey(EVENTHUB_ID, BTN_Y, 0, AKEYCODE_BUTTON_Y, 0);
3824
3825 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003826 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Chris Yea52ade12020-08-27 16:49:20 -07003827
Chris Yea52ade12020-08-27 16:49:20 -07003828 // Meta state should be AMETA_NONE after reset
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003829 std::list<NotifyArgs> unused = mapper.reset(ARBITRARY_TIME);
Chris Yea52ade12020-08-27 16:49:20 -07003830 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3831 // Meta state should be AMETA_NONE with update, as device doesn't have the keys.
3832 mapper.updateMetaState(AKEYCODE_NUM_LOCK);
3833 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3834
3835 NotifyKeyArgs args;
3836 // Press button "A"
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003837 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_A, 1);
Chris Yea52ade12020-08-27 16:49:20 -07003838 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3839 ASSERT_EQ(AMETA_NONE, args.metaState);
3840 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3841 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3842 ASSERT_EQ(AKEYCODE_BUTTON_A, args.keyCode);
3843
3844 // Button up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003845 process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_KEY, BTN_A, 0);
Chris Yea52ade12020-08-27 16:49:20 -07003846 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3847 ASSERT_EQ(AMETA_NONE, args.metaState);
3848 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3849 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3850 ASSERT_EQ(AKEYCODE_BUTTON_A, args.keyCode);
3851}
3852
Arthur Hung2c9a3342019-07-23 14:18:59 +08003853TEST_F(KeyboardInputMapperTest, Configure_AssignsDisplayPort) {
3854 // keyboard 1.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003855 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3856 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3857 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3858 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003859
3860 // keyboard 2.
3861 const std::string USB2 = "USB2";
arthurhungdcef2dc2020-08-11 14:47:50 +08003862 const std::string DEVICE_NAME2 = "KEYBOARD2";
Arthur Hung2c9a3342019-07-23 14:18:59 +08003863 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003864 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
arthurhungdcef2dc2020-08-11 14:47:50 +08003865 std::shared_ptr<InputDevice> device2 =
3866 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
Dominik Laskowski2f01d772022-03-23 16:01:29 -07003867 ftl::Flags<InputDeviceClass>(0));
arthurhungdcef2dc2020-08-11 14:47:50 +08003868
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003869 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3870 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3871 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3872 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003873
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003874 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003875 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003876
Arpit Singh67ca6842023-04-26 14:43:16 +00003877 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003878 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003879 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3880 mFakePolicy
3881 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003882 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003883 std::list<NotifyArgs> unused =
3884 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003885 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003886 unused += device2->reset(ARBITRARY_TIME);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003887
3888 // Prepared displays and associated info.
3889 constexpr uint8_t hdmi1 = 0;
3890 constexpr uint8_t hdmi2 = 1;
3891 const std::string SECONDARY_UNIQUE_ID = "local:1";
3892
3893 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
3894 mFakePolicy->addInputPortAssociation(USB2, hdmi2);
3895
3896 // No associated display viewport found, should disable the device.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003897 unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003898 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003899 ASSERT_FALSE(device2->isEnabled());
3900
3901 // Prepare second display.
Linnan Li13bf76a2024-05-05 19:18:02 +08003902 constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
Michael Wrighta9cf4192022-12-01 23:46:39 +00003903 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003904 UNIQUE_ID, hdmi1, ViewportType::INTERNAL);
Michael Wrighta9cf4192022-12-01 23:46:39 +00003905 setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003906 SECONDARY_UNIQUE_ID, hdmi2, ViewportType::EXTERNAL);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003907 // Default device will reconfigure above, need additional reconfiguration for another device.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003908 unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003909 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003910
3911 // Device should be enabled after the associated display is found.
3912 ASSERT_TRUE(mDevice->isEnabled());
3913 ASSERT_TRUE(device2->isEnabled());
3914
3915 // Test pad key events
3916 ASSERT_NO_FATAL_FAILURE(
3917 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
3918 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3919 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3920 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3921 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3922 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3923 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3924
3925 ASSERT_NO_FATAL_FAILURE(
3926 testDPadKeyRotation(mapper2, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, newDisplayId));
3927 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3928 AKEYCODE_DPAD_RIGHT, newDisplayId));
3929 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3930 AKEYCODE_DPAD_DOWN, newDisplayId));
3931 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3932 AKEYCODE_DPAD_LEFT, newDisplayId));
3933}
Michael Wrightd02c5b62014-02-10 15:10:22 -08003934
arthurhungc903df12020-08-11 15:08:42 +08003935TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleAfterReattach) {
3936 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3937 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3938 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3939 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3940 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3941 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3942
3943 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003944 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003945 // Initial metastate is AMETA_NONE.
3946 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
arthurhungc903df12020-08-11 15:08:42 +08003947
3948 // Initialization should have turned all of the lights off.
3949 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3950 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3951 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3952
3953 // Toggle caps lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003954 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3955 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003956 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3957 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
3958
3959 // Toggle num lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003960 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3961 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003962 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3963 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
3964
3965 // Toggle scroll lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003966 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3967 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003968 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3969 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
3970
3971 mFakeEventHub->removeDevice(EVENTHUB_ID);
3972 mReader->loopOnce();
3973
3974 // keyboard 2 should default toggle keys.
3975 const std::string USB2 = "USB2";
3976 const std::string DEVICE_NAME2 = "KEYBOARD2";
3977 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
3978 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
3979 std::shared_ptr<InputDevice> device2 =
3980 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
Dominik Laskowski2f01d772022-03-23 16:01:29 -07003981 ftl::Flags<InputDeviceClass>(0));
arthurhungc903df12020-08-11 15:08:42 +08003982 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3983 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
3984 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3985 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3986 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3987 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3988
Arpit Singh67ca6842023-04-26 14:43:16 +00003989 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
arthurhung6fe95782020-10-05 22:41:16 +08003990 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003991 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3992 mFakePolicy
3993 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003994 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003995 std::list<NotifyArgs> unused =
3996 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003997 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003998 unused += device2->reset(ARBITRARY_TIME);
arthurhungc903df12020-08-11 15:08:42 +08003999
4000 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_CAPSL));
4001 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_NUML));
4002 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_SCROLLL));
arthurhung6fe95782020-10-05 22:41:16 +08004003 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON,
4004 mapper2.getMetaState());
arthurhungc903df12020-08-11 15:08:42 +08004005}
4006
Arthur Hungcb40a002021-08-03 14:31:01 +00004007TEST_F(KeyboardInputMapperTest, Process_toggleCapsLockState) {
4008 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
4009 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
4010 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
4011
4012 // Suppose we have two mappers. (DPAD + KEYBOARD)
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004013 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD);
Arthur Hungcb40a002021-08-03 14:31:01 +00004014 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004015 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08004016 // Initial metastate is AMETA_NONE.
4017 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Arthur Hungcb40a002021-08-03 14:31:01 +00004018
4019 mReader->toggleCapsLockState(DEVICE_ID);
4020 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
4021}
4022
Arthur Hungfb3cc112022-04-13 07:39:50 +00004023TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleInMultiDevices) {
4024 // keyboard 1.
4025 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
4026 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
4027 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
4028 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
4029 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
4030 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
4031
4032 KeyboardInputMapper& mapper1 =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004033 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hungfb3cc112022-04-13 07:39:50 +00004034
4035 // keyboard 2.
4036 const std::string USB2 = "USB2";
4037 const std::string DEVICE_NAME2 = "KEYBOARD2";
4038 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
4039 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
4040 std::shared_ptr<InputDevice> device2 =
4041 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
4042 ftl::Flags<InputDeviceClass>(0));
4043 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
4044 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
4045 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
4046 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
4047 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
4048 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
4049
Arpit Singh67ca6842023-04-26 14:43:16 +00004050 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
Arthur Hungfb3cc112022-04-13 07:39:50 +00004051 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00004052 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
4053 mFakePolicy
4054 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004055 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07004056 std::list<NotifyArgs> unused =
4057 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004058 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07004059 unused += device2->reset(ARBITRARY_TIME);
Arthur Hungfb3cc112022-04-13 07:39:50 +00004060
Arthur Hung95f68612022-04-07 14:08:22 +08004061 // Initial metastate is AMETA_NONE.
4062 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
4063 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
4064
4065 // Toggle num lock on and off.
4066 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
4067 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Arthur Hungfb3cc112022-04-13 07:39:50 +00004068 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
4069 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper1.getMetaState());
4070 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper2.getMetaState());
4071
4072 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
4073 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
4074 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
4075 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
4076 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
4077
4078 // Toggle caps lock on and off.
4079 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
4080 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
4081 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
4082 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper1.getMetaState());
4083 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper2.getMetaState());
4084
4085 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
4086 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
4087 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
4088 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
4089 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
4090
4091 // Toggle scroll lock on and off.
4092 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
4093 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
4094 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
4095 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper1.getMetaState());
4096 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper2.getMetaState());
4097
4098 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
4099 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
4100 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
4101 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
4102 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
4103}
4104
Arthur Hung2141d542022-08-23 07:45:21 +00004105TEST_F(KeyboardInputMapperTest, Process_DisabledDevice) {
4106 const int32_t USAGE_A = 0x070004;
4107 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4108 mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
4109
4110 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004111 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung2141d542022-08-23 07:45:21 +00004112 // Key down by scan code.
4113 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
4114 NotifyKeyArgs args;
4115 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4116 ASSERT_EQ(DEVICE_ID, args.deviceId);
4117 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4118 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4119 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
4120 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4121 ASSERT_EQ(KEY_HOME, args.scanCode);
4122 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
4123
4124 // Disable device, it should synthesize cancellation events for down events.
4125 mFakePolicy->addDisabledDevice(DEVICE_ID);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004126 configureDevice(InputReaderConfiguration::Change::ENABLED_STATE);
Arthur Hung2141d542022-08-23 07:45:21 +00004127
4128 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4129 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
4130 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4131 ASSERT_EQ(KEY_HOME, args.scanCode);
4132 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_CANCELED, args.flags);
4133}
4134
Zixuan Qufecb6062022-11-12 04:44:31 +00004135TEST_F(KeyboardInputMapperTest, Configure_AssignKeyboardLayoutInfo) {
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004136 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Zixuan Qufecb6062022-11-12 04:44:31 +00004137 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004138 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
4139 /*changes=*/{});
Zixuan Qufecb6062022-11-12 04:44:31 +00004140
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +00004141 uint32_t generation = mReader->getContext()->getGeneration();
Zixuan Qufecb6062022-11-12 04:44:31 +00004142 mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
4143
4144 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004145 InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
Zixuan Qufecb6062022-11-12 04:44:31 +00004146
4147 InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
4148 ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.languageTag,
4149 deviceInfo.getKeyboardLayoutInfo()->languageTag);
4150 ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.layoutType,
4151 deviceInfo.getKeyboardLayoutInfo()->layoutType);
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +00004152 ASSERT_TRUE(mReader->getContext()->getGeneration() != generation);
4153
4154 // Call change layout association with the same values: Generation shouldn't change
4155 generation = mReader->getContext()->getGeneration();
4156 mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
4157 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
4158 InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
4159 ASSERT_TRUE(mReader->getContext()->getGeneration() == generation);
Zixuan Qufecb6062022-11-12 04:44:31 +00004160}
4161
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004162TEST_F(KeyboardInputMapperTest, LayoutInfoCorrectlyMapped) {
4163 mFakeEventHub->setRawLayoutInfo(EVENTHUB_ID,
4164 RawLayoutInfo{.languageTag = "en", .layoutType = "extended"});
4165
4166 // Configuration
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004167 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004168 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004169 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004170
4171 ASSERT_EQ("en", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->languageTag);
4172 ASSERT_EQ("extended", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->layoutType);
4173}
4174
Justin Chung71ddb432023-03-27 04:29:07 +00004175TEST_F(KeyboardInputMapperTest, Process_GesureEventToSetFlagKeepTouchMode) {
4176 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, POLICY_FLAG_GESTURE);
4177 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004178 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Justin Chung71ddb432023-03-27 04:29:07 +00004179 NotifyKeyArgs args;
4180
4181 // Key down
4182 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFT, 1);
4183 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4184 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_KEEP_TOUCH_MODE, args.flags);
4185}
4186
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004187// --- KeyboardInputMapperTest_ExternalAlphabeticDevice ---
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004188
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004189class KeyboardInputMapperTest_ExternalAlphabeticDevice : public InputMapperTest {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004190protected:
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004191 void SetUp() override {
4192 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
4193 InputDeviceClass::ALPHAKEY | InputDeviceClass::EXTERNAL);
4194 }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004195};
4196
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004197// --- KeyboardInputMapperTest_ExternalNonAlphabeticDevice ---
4198
4199class KeyboardInputMapperTest_ExternalNonAlphabeticDevice : public InputMapperTest {
4200protected:
4201 void SetUp() override {
4202 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
4203 InputDeviceClass::EXTERNAL);
4204 }
4205};
4206
4207TEST_F(KeyboardInputMapperTest_ExternalAlphabeticDevice, WakeBehavior_AlphabeticKeyboard) {
Vaibhav Devmurari16257862023-03-06 10:06:32 +00004208 // For external devices, keys will trigger wake on key down. Media keys should also trigger
4209 // wake if triggered from external devices.
Powei Fengd041c5d2019-05-03 17:11:33 -07004210
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004211 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, 0);
4212 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
4213 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
4214 POLICY_FLAG_WAKE);
Powei Fengd041c5d2019-05-03 17:11:33 -07004215
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004216 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004217 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Powei Fengd041c5d2019-05-03 17:11:33 -07004218
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004219 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004220 NotifyKeyArgs args;
4221 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4222 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4223
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004224 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004225 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4226 ASSERT_EQ(uint32_t(0), args.policyFlags);
4227
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004228 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004229 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Vaibhav Devmurari16257862023-03-06 10:06:32 +00004230 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
Powei Fengd041c5d2019-05-03 17:11:33 -07004231
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004232 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004233 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4234 ASSERT_EQ(uint32_t(0), args.policyFlags);
4235
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004236 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004237 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4238 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4239
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004240 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004241 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4242 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4243}
4244
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004245TEST_F(KeyboardInputMapperTest_ExternalNonAlphabeticDevice, WakeBehavior_NonAlphabeticKeyboard) {
Vaibhav Devmurari2681a812024-01-11 00:15:35 +00004246 // For external devices, keys will trigger wake on key down. Media keys should not trigger
4247 // wake if triggered from external non-alphaebtic keyboard (e.g. headsets).
4248
4249 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
4250 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
4251 POLICY_FLAG_WAKE);
4252
4253 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004254 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmurari2681a812024-01-11 00:15:35 +00004255
4256 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
4257 NotifyKeyArgs args;
4258 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4259 ASSERT_EQ(uint32_t(0), args.policyFlags);
4260
4261 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
4262 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4263 ASSERT_EQ(uint32_t(0), args.policyFlags);
4264
4265 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1);
4266 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4267 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4268
4269 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0);
4270 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4271 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4272}
4273
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004274TEST_F(KeyboardInputMapperTest_ExternalAlphabeticDevice, DoNotWakeByDefaultBehavior) {
Powei Fengd041c5d2019-05-03 17:11:33 -07004275 // Tv Remote key's wake behavior is prescribed by the keylayout file.
Powei Fengd041c5d2019-05-03 17:11:33 -07004276
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004277 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4278 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
4279 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, POLICY_FLAG_WAKE);
Powei Fengd041c5d2019-05-03 17:11:33 -07004280
Powei Fengd041c5d2019-05-03 17:11:33 -07004281 addConfigurationProperty("keyboard.doNotWakeByDefault", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004282 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004283 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Powei Fengd041c5d2019-05-03 17:11:33 -07004284
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004285 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004286 NotifyKeyArgs args;
4287 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4288 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4289
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004290 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004291 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4292 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4293
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004294 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_DOWN, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004295 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4296 ASSERT_EQ(uint32_t(0), args.policyFlags);
4297
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004298 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_DOWN, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004299 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4300 ASSERT_EQ(uint32_t(0), args.policyFlags);
4301
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004302 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004303 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4304 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4305
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004306 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004307 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4308 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4309}
4310
Michael Wrightd02c5b62014-02-10 15:10:22 -08004311// --- TouchInputMapperTest ---
4312
4313class TouchInputMapperTest : public InputMapperTest {
4314protected:
4315 static const int32_t RAW_X_MIN;
4316 static const int32_t RAW_X_MAX;
4317 static const int32_t RAW_Y_MIN;
4318 static const int32_t RAW_Y_MAX;
4319 static const int32_t RAW_TOUCH_MIN;
4320 static const int32_t RAW_TOUCH_MAX;
4321 static const int32_t RAW_TOOL_MIN;
4322 static const int32_t RAW_TOOL_MAX;
4323 static const int32_t RAW_PRESSURE_MIN;
4324 static const int32_t RAW_PRESSURE_MAX;
4325 static const int32_t RAW_ORIENTATION_MIN;
4326 static const int32_t RAW_ORIENTATION_MAX;
4327 static const int32_t RAW_DISTANCE_MIN;
4328 static const int32_t RAW_DISTANCE_MAX;
4329 static const int32_t RAW_TILT_MIN;
4330 static const int32_t RAW_TILT_MAX;
4331 static const int32_t RAW_ID_MIN;
4332 static const int32_t RAW_ID_MAX;
4333 static const int32_t RAW_SLOT_MIN;
4334 static const int32_t RAW_SLOT_MAX;
4335 static const float X_PRECISION;
4336 static const float Y_PRECISION;
Santos Cordonfa5cf462017-04-05 10:37:00 -07004337 static const float X_PRECISION_VIRTUAL;
4338 static const float Y_PRECISION_VIRTUAL;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004339
4340 static const float GEOMETRIC_SCALE;
Jason Gerecke489fda82012-09-07 17:19:40 -07004341 static const TouchAffineTransformation AFFINE_TRANSFORM;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004342
4343 static const VirtualKeyDefinition VIRTUAL_KEYS[2];
4344
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07004345 const std::string UNIQUE_ID = "local:0";
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004346 const std::string SECONDARY_UNIQUE_ID = "local:1";
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07004347
Michael Wrightd02c5b62014-02-10 15:10:22 -08004348 enum Axes {
4349 POSITION = 1 << 0,
4350 TOUCH = 1 << 1,
4351 TOOL = 1 << 2,
4352 PRESSURE = 1 << 3,
4353 ORIENTATION = 1 << 4,
4354 MINOR = 1 << 5,
4355 ID = 1 << 6,
4356 DISTANCE = 1 << 7,
4357 TILT = 1 << 8,
4358 SLOT = 1 << 9,
4359 TOOL_TYPE = 1 << 10,
4360 };
4361
Michael Wrighta9cf4192022-12-01 23:46:39 +00004362 void prepareDisplay(ui::Rotation orientation, std::optional<uint8_t> port = NO_PORT);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004363 void prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port = NO_PORT);
Michael Wrighta9cf4192022-12-01 23:46:39 +00004364 void prepareVirtualDisplay(ui::Rotation orientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004365 void prepareVirtualKeys();
Jason Gerecke489fda82012-09-07 17:19:40 -07004366 void prepareLocationCalibration();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004367 int32_t toRawX(float displayX);
4368 int32_t toRawY(float displayY);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07004369 int32_t toRotatedRawX(float displayX);
4370 int32_t toRotatedRawY(float displayY);
Jason Gerecke489fda82012-09-07 17:19:40 -07004371 float toCookedX(float rawX, float rawY);
4372 float toCookedY(float rawX, float rawY);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004373 float toDisplayX(int32_t rawX);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004374 float toDisplayX(int32_t rawX, int32_t displayWidth);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004375 float toDisplayY(int32_t rawY);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004376 float toDisplayY(int32_t rawY, int32_t displayHeight);
4377
Michael Wrightd02c5b62014-02-10 15:10:22 -08004378};
4379
4380const int32_t TouchInputMapperTest::RAW_X_MIN = 25;
4381const int32_t TouchInputMapperTest::RAW_X_MAX = 1019;
4382const int32_t TouchInputMapperTest::RAW_Y_MIN = 30;
4383const int32_t TouchInputMapperTest::RAW_Y_MAX = 1009;
4384const int32_t TouchInputMapperTest::RAW_TOUCH_MIN = 0;
4385const int32_t TouchInputMapperTest::RAW_TOUCH_MAX = 31;
4386const int32_t TouchInputMapperTest::RAW_TOOL_MIN = 0;
4387const int32_t TouchInputMapperTest::RAW_TOOL_MAX = 15;
Michael Wrightaa449c92017-12-13 21:21:43 +00004388const int32_t TouchInputMapperTest::RAW_PRESSURE_MIN = 0;
4389const int32_t TouchInputMapperTest::RAW_PRESSURE_MAX = 255;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004390const int32_t TouchInputMapperTest::RAW_ORIENTATION_MIN = -7;
4391const int32_t TouchInputMapperTest::RAW_ORIENTATION_MAX = 7;
4392const int32_t TouchInputMapperTest::RAW_DISTANCE_MIN = 0;
4393const int32_t TouchInputMapperTest::RAW_DISTANCE_MAX = 7;
4394const int32_t TouchInputMapperTest::RAW_TILT_MIN = 0;
4395const int32_t TouchInputMapperTest::RAW_TILT_MAX = 150;
4396const int32_t TouchInputMapperTest::RAW_ID_MIN = 0;
4397const int32_t TouchInputMapperTest::RAW_ID_MAX = 9;
4398const int32_t TouchInputMapperTest::RAW_SLOT_MIN = 0;
4399const int32_t TouchInputMapperTest::RAW_SLOT_MAX = 9;
4400const float TouchInputMapperTest::X_PRECISION = float(RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH;
4401const float TouchInputMapperTest::Y_PRECISION = float(RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT;
Santos Cordonfa5cf462017-04-05 10:37:00 -07004402const float TouchInputMapperTest::X_PRECISION_VIRTUAL =
4403 float(RAW_X_MAX - RAW_X_MIN + 1) / VIRTUAL_DISPLAY_WIDTH;
4404const float TouchInputMapperTest::Y_PRECISION_VIRTUAL =
4405 float(RAW_Y_MAX - RAW_Y_MIN + 1) / VIRTUAL_DISPLAY_HEIGHT;
Jason Gerecke489fda82012-09-07 17:19:40 -07004406const TouchAffineTransformation TouchInputMapperTest::AFFINE_TRANSFORM =
4407 TouchAffineTransformation(1, -2, 3, -4, 5, -6);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004408
4409const float TouchInputMapperTest::GEOMETRIC_SCALE =
4410 avg(float(DISPLAY_WIDTH) / (RAW_X_MAX - RAW_X_MIN + 1),
4411 float(DISPLAY_HEIGHT) / (RAW_Y_MAX - RAW_Y_MIN + 1));
4412
4413const VirtualKeyDefinition TouchInputMapperTest::VIRTUAL_KEYS[2] = {
4414 { KEY_HOME, 60, DISPLAY_HEIGHT + 15, 20, 20 },
4415 { KEY_MENU, DISPLAY_HEIGHT - 60, DISPLAY_WIDTH + 15, 20, 20 },
4416};
4417
Michael Wrighta9cf4192022-12-01 23:46:39 +00004418void TouchInputMapperTest::prepareDisplay(ui::Rotation orientation, std::optional<uint8_t> port) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01004419 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
4420 port, ViewportType::INTERNAL);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004421}
4422
4423void TouchInputMapperTest::prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port) {
4424 setDisplayInfoAndReconfigure(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00004425 ui::ROTATION_0, SECONDARY_UNIQUE_ID, port, type);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004426}
4427
Michael Wrighta9cf4192022-12-01 23:46:39 +00004428void TouchInputMapperTest::prepareVirtualDisplay(ui::Rotation orientation) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01004429 setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH, VIRTUAL_DISPLAY_HEIGHT,
4430 orientation, VIRTUAL_DISPLAY_UNIQUE_ID, NO_PORT,
4431 ViewportType::VIRTUAL);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004432}
4433
Michael Wrightd02c5b62014-02-10 15:10:22 -08004434void TouchInputMapperTest::prepareVirtualKeys() {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004435 mFakeEventHub->addVirtualKeyDefinition(EVENTHUB_ID, VIRTUAL_KEYS[0]);
4436 mFakeEventHub->addVirtualKeyDefinition(EVENTHUB_ID, VIRTUAL_KEYS[1]);
4437 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4438 mFakeEventHub->addKey(EVENTHUB_ID, KEY_MENU, 0, AKEYCODE_MENU, POLICY_FLAG_WAKE);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004439}
4440
Jason Gerecke489fda82012-09-07 17:19:40 -07004441void TouchInputMapperTest::prepareLocationCalibration() {
4442 mFakePolicy->setTouchAffineTransformation(AFFINE_TRANSFORM);
4443}
4444
Michael Wrightd02c5b62014-02-10 15:10:22 -08004445int32_t TouchInputMapperTest::toRawX(float displayX) {
4446 return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH + RAW_X_MIN);
4447}
4448
4449int32_t TouchInputMapperTest::toRawY(float displayY) {
4450 return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT + RAW_Y_MIN);
4451}
4452
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07004453int32_t TouchInputMapperTest::toRotatedRawX(float displayX) {
4454 return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_HEIGHT + RAW_X_MIN);
4455}
4456
4457int32_t TouchInputMapperTest::toRotatedRawY(float displayY) {
4458 return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_WIDTH + RAW_Y_MIN);
4459}
4460
Jason Gerecke489fda82012-09-07 17:19:40 -07004461float TouchInputMapperTest::toCookedX(float rawX, float rawY) {
4462 AFFINE_TRANSFORM.applyTo(rawX, rawY);
4463 return rawX;
4464}
4465
4466float TouchInputMapperTest::toCookedY(float rawX, float rawY) {
4467 AFFINE_TRANSFORM.applyTo(rawX, rawY);
4468 return rawY;
4469}
4470
Michael Wrightd02c5b62014-02-10 15:10:22 -08004471float TouchInputMapperTest::toDisplayX(int32_t rawX) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004472 return toDisplayX(rawX, DISPLAY_WIDTH);
4473}
4474
4475float TouchInputMapperTest::toDisplayX(int32_t rawX, int32_t displayWidth) {
4476 return float(rawX - RAW_X_MIN) * displayWidth / (RAW_X_MAX - RAW_X_MIN + 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004477}
4478
4479float TouchInputMapperTest::toDisplayY(int32_t rawY) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004480 return toDisplayY(rawY, DISPLAY_HEIGHT);
4481}
4482
4483float TouchInputMapperTest::toDisplayY(int32_t rawY, int32_t displayHeight) {
4484 return float(rawY - RAW_Y_MIN) * displayHeight / (RAW_Y_MAX - RAW_Y_MIN + 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004485}
4486
4487
4488// --- SingleTouchInputMapperTest ---
4489
4490class SingleTouchInputMapperTest : public TouchInputMapperTest {
4491protected:
4492 void prepareButtons();
4493 void prepareAxes(int axes);
4494
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004495 void processDown(SingleTouchInputMapper& mapper, int32_t x, int32_t y);
4496 void processMove(SingleTouchInputMapper& mapper, int32_t x, int32_t y);
4497 void processUp(SingleTouchInputMapper& mappery);
4498 void processPressure(SingleTouchInputMapper& mapper, int32_t pressure);
4499 void processToolMajor(SingleTouchInputMapper& mapper, int32_t toolMajor);
4500 void processDistance(SingleTouchInputMapper& mapper, int32_t distance);
4501 void processTilt(SingleTouchInputMapper& mapper, int32_t tiltX, int32_t tiltY);
4502 void processKey(SingleTouchInputMapper& mapper, int32_t code, int32_t value);
4503 void processSync(SingleTouchInputMapper& mapper);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004504};
4505
4506void SingleTouchInputMapperTest::prepareButtons() {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004507 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004508}
4509
4510void SingleTouchInputMapperTest::prepareAxes(int axes) {
4511 if (axes & POSITION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004512 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
4513 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004514 }
4515 if (axes & PRESSURE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004516 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_PRESSURE, RAW_PRESSURE_MIN,
4517 RAW_PRESSURE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004518 }
4519 if (axes & TOOL) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004520 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TOOL_WIDTH, RAW_TOOL_MIN, RAW_TOOL_MAX, 0,
4521 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004522 }
4523 if (axes & DISTANCE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004524 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_DISTANCE, RAW_DISTANCE_MIN,
4525 RAW_DISTANCE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004526 }
4527 if (axes & TILT) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004528 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TILT_X, RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
4529 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TILT_Y, RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004530 }
4531}
4532
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004533void SingleTouchInputMapperTest::processDown(SingleTouchInputMapper& mapper, int32_t x, int32_t y) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004534 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
4535 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, x);
4536 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, y);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004537}
4538
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004539void SingleTouchInputMapperTest::processMove(SingleTouchInputMapper& mapper, int32_t x, int32_t y) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004540 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, x);
4541 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, y);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004542}
4543
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004544void SingleTouchInputMapperTest::processUp(SingleTouchInputMapper& mapper) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004545 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004546}
4547
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004548void SingleTouchInputMapperTest::processPressure(SingleTouchInputMapper& mapper, int32_t pressure) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004549 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_PRESSURE, pressure);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004550}
4551
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004552void SingleTouchInputMapperTest::processToolMajor(SingleTouchInputMapper& mapper,
4553 int32_t toolMajor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004554 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TOOL_WIDTH, toolMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004555}
4556
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004557void SingleTouchInputMapperTest::processDistance(SingleTouchInputMapper& mapper, int32_t distance) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004558 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_DISTANCE, distance);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004559}
4560
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004561void SingleTouchInputMapperTest::processTilt(SingleTouchInputMapper& mapper, int32_t tiltX,
4562 int32_t tiltY) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004563 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TILT_X, tiltX);
4564 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TILT_Y, tiltY);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004565}
4566
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004567void SingleTouchInputMapperTest::processKey(SingleTouchInputMapper& mapper, int32_t code,
4568 int32_t value) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004569 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004570}
4571
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004572void SingleTouchInputMapperTest::processSync(SingleTouchInputMapper& mapper) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004573 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004574}
4575
Michael Wrightd02c5b62014-02-10 15:10:22 -08004576TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndNotACursor_ReturnsPointer) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004577 prepareButtons();
4578 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00004579 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004580
Josep del Río2d8c79a2023-01-23 19:33:50 +00004581 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004582}
4583
Michael Wrightd02c5b62014-02-10 15:10:22 -08004584TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004585 prepareButtons();
4586 prepareAxes(POSITION);
4587 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00004588 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004589
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004590 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004591}
4592
4593TEST_F(SingleTouchInputMapperTest, GetKeyCodeState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004594 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004595 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004596 prepareButtons();
4597 prepareAxes(POSITION);
4598 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004599 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004600
4601 // Unknown key.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004602 ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004603
4604 // Virtual key is down.
4605 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4606 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4607 processDown(mapper, x, y);
4608 processSync(mapper);
4609 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4610
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004611 ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004612
4613 // Virtual key is up.
4614 processUp(mapper);
4615 processSync(mapper);
4616 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4617
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004618 ASSERT_EQ(AKEY_STATE_UP, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004619}
4620
4621TEST_F(SingleTouchInputMapperTest, GetScanCodeState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004622 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004623 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004624 prepareButtons();
4625 prepareAxes(POSITION);
4626 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004627 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004628
4629 // Unknown key.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004630 ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004631
4632 // Virtual key is down.
4633 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4634 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4635 processDown(mapper, x, y);
4636 processSync(mapper);
4637 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4638
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004639 ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004640
4641 // Virtual key is up.
4642 processUp(mapper);
4643 processSync(mapper);
4644 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4645
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004646 ASSERT_EQ(AKEY_STATE_UP, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004647}
4648
4649TEST_F(SingleTouchInputMapperTest, MarkSupportedKeyCodes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004650 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004651 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004652 prepareButtons();
4653 prepareAxes(POSITION);
4654 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004655 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004656
Michael Wrightd02c5b62014-02-10 15:10:22 -08004657 uint8_t flags[2] = { 0, 0 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07004658 ASSERT_TRUE(
4659 mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_HOME, AKEYCODE_A}, flags));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004660 ASSERT_TRUE(flags[0]);
4661 ASSERT_FALSE(flags[1]);
4662}
4663
4664TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNormally_SendsKeyDownAndKeyUp) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004665 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004666 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004667 prepareButtons();
4668 prepareAxes(POSITION);
4669 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004670 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004671
arthurhungdcef2dc2020-08-11 14:47:50 +08004672 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004673
4674 NotifyKeyArgs args;
4675
4676 // Press virtual key.
4677 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4678 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4679 processDown(mapper, x, y);
4680 processSync(mapper);
4681
4682 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4683 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4684 ASSERT_EQ(DEVICE_ID, args.deviceId);
4685 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4686 ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
4687 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
4688 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
4689 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4690 ASSERT_EQ(KEY_HOME, args.scanCode);
4691 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
4692 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
4693
4694 // Release virtual key.
4695 processUp(mapper);
4696 processSync(mapper);
4697
4698 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4699 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4700 ASSERT_EQ(DEVICE_ID, args.deviceId);
4701 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4702 ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
4703 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
4704 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
4705 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4706 ASSERT_EQ(KEY_HOME, args.scanCode);
4707 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
4708 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
4709
4710 // Should not have sent any motions.
4711 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4712}
4713
4714TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfBounds_SendsKeyDownAndKeyCancel) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004715 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004716 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004717 prepareButtons();
4718 prepareAxes(POSITION);
4719 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004720 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004721
arthurhungdcef2dc2020-08-11 14:47:50 +08004722 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004723
4724 NotifyKeyArgs keyArgs;
4725
4726 // Press virtual key.
4727 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4728 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4729 processDown(mapper, x, y);
4730 processSync(mapper);
4731
4732 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
4733 ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
4734 ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
4735 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
4736 ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
4737 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
4738 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, keyArgs.flags);
4739 ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
4740 ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
4741 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
4742 ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
4743
4744 // Move out of bounds. This should generate a cancel and a pointer down since we moved
4745 // into the display area.
4746 y -= 100;
4747 processMove(mapper, x, y);
4748 processSync(mapper);
4749
4750 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
4751 ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
4752 ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
4753 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
4754 ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
4755 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
4756 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
4757 | AKEY_EVENT_FLAG_CANCELED, keyArgs.flags);
4758 ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
4759 ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
4760 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
4761 ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
4762
4763 NotifyMotionArgs motionArgs;
4764 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4765 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4766 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4767 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4768 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4769 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4770 ASSERT_EQ(0, motionArgs.flags);
4771 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4772 ASSERT_EQ(0, motionArgs.buttonState);
4773 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004774 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004775 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004776 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004777 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4778 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4779 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4780 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4781 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4782
4783 // Keep moving out of bounds. Should generate a pointer move.
4784 y -= 50;
4785 processMove(mapper, x, y);
4786 processSync(mapper);
4787
4788 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4789 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4790 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4791 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4792 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4793 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
4794 ASSERT_EQ(0, motionArgs.flags);
4795 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4796 ASSERT_EQ(0, motionArgs.buttonState);
4797 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004798 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004799 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004800 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004801 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4802 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4803 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4804 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4805 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4806
4807 // Release out of bounds. Should generate a pointer up.
4808 processUp(mapper);
4809 processSync(mapper);
4810
4811 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4812 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4813 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4814 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4815 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4816 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4817 ASSERT_EQ(0, motionArgs.flags);
4818 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4819 ASSERT_EQ(0, motionArgs.buttonState);
4820 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004821 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004822 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004823 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004824 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4825 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4826 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4827 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4828 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4829
4830 // Should not have sent any more keys or motions.
4831 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4832 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4833}
4834
4835TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMovesIn_SendsDownAsTouchEntersDisplay) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004836 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004837 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004838 prepareButtons();
4839 prepareAxes(POSITION);
4840 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004841 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004842
arthurhungdcef2dc2020-08-11 14:47:50 +08004843 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004844
4845 NotifyMotionArgs motionArgs;
4846
4847 // Initially go down out of bounds.
4848 int32_t x = -10;
4849 int32_t y = -10;
4850 processDown(mapper, x, y);
4851 processSync(mapper);
4852
4853 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4854
4855 // Move into the display area. Should generate a pointer down.
4856 x = 50;
4857 y = 75;
4858 processMove(mapper, x, y);
4859 processSync(mapper);
4860
4861 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4862 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4863 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4864 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4865 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4866 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4867 ASSERT_EQ(0, motionArgs.flags);
4868 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4869 ASSERT_EQ(0, motionArgs.buttonState);
4870 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004871 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004872 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004873 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004874 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4875 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4876 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4877 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4878 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4879
4880 // Release. Should generate a pointer up.
4881 processUp(mapper);
4882 processSync(mapper);
4883
4884 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4885 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4886 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4887 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4888 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4889 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4890 ASSERT_EQ(0, motionArgs.flags);
4891 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4892 ASSERT_EQ(0, motionArgs.buttonState);
4893 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004894 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004895 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004896 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004897 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4898 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4899 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4900 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4901 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4902
4903 // Should not have sent any more keys or motions.
4904 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4905 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4906}
4907
Santos Cordonfa5cf462017-04-05 10:37:00 -07004908TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture_VirtualDisplay) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004909 addConfigurationProperty("touch.deviceType", "touchScreen");
4910 addConfigurationProperty("touch.displayId", VIRTUAL_DISPLAY_UNIQUE_ID);
4911
Michael Wrighta9cf4192022-12-01 23:46:39 +00004912 prepareVirtualDisplay(ui::ROTATION_0);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004913 prepareButtons();
4914 prepareAxes(POSITION);
4915 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004916 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Santos Cordonfa5cf462017-04-05 10:37:00 -07004917
arthurhungdcef2dc2020-08-11 14:47:50 +08004918 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004919
4920 NotifyMotionArgs motionArgs;
4921
4922 // Down.
4923 int32_t x = 100;
4924 int32_t y = 125;
4925 processDown(mapper, x, y);
4926 processSync(mapper);
4927
4928 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4929 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4930 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4931 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4932 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4933 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4934 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4935 ASSERT_EQ(0, motionArgs.flags);
4936 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4937 ASSERT_EQ(0, motionArgs.buttonState);
4938 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004939 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004940 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004941 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004942 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4943 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4944 1, 0, 0, 0, 0, 0, 0, 0));
4945 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4946 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4947 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4948
4949 // Move.
4950 x += 50;
4951 y += 75;
4952 processMove(mapper, x, y);
4953 processSync(mapper);
4954
4955 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4956 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4957 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4958 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4959 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4960 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4961 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
4962 ASSERT_EQ(0, motionArgs.flags);
4963 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4964 ASSERT_EQ(0, motionArgs.buttonState);
4965 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004966 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004967 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004968 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004969 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4970 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4971 1, 0, 0, 0, 0, 0, 0, 0));
4972 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4973 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4974 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4975
4976 // Up.
4977 processUp(mapper);
4978 processSync(mapper);
4979
4980 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4981 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4982 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4983 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4984 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4985 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4986 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4987 ASSERT_EQ(0, motionArgs.flags);
4988 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4989 ASSERT_EQ(0, motionArgs.buttonState);
4990 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004991 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004992 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004993 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004994 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4995 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4996 1, 0, 0, 0, 0, 0, 0, 0));
4997 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4998 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4999 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5000
5001 // Should not have sent any more keys or motions.
5002 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5003 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5004}
5005
Michael Wrightd02c5b62014-02-10 15:10:22 -08005006TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005007 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005008 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005009 prepareButtons();
5010 prepareAxes(POSITION);
5011 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00005012 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005013
arthurhungdcef2dc2020-08-11 14:47:50 +08005014 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005015
5016 NotifyMotionArgs motionArgs;
5017
5018 // Down.
5019 int32_t x = 100;
5020 int32_t y = 125;
5021 processDown(mapper, x, y);
5022 processSync(mapper);
5023
5024 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5025 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5026 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5027 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5028 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5029 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5030 ASSERT_EQ(0, motionArgs.flags);
5031 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5032 ASSERT_EQ(0, motionArgs.buttonState);
5033 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005034 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08005035 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005036 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005037 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5038 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
5039 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5040 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5041 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5042
5043 // Move.
5044 x += 50;
5045 y += 75;
5046 processMove(mapper, x, y);
5047 processSync(mapper);
5048
5049 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5050 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5051 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5052 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5053 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5054 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5055 ASSERT_EQ(0, motionArgs.flags);
5056 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5057 ASSERT_EQ(0, motionArgs.buttonState);
5058 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005059 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08005060 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005061 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005062 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5063 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
5064 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5065 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5066 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5067
5068 // Up.
5069 processUp(mapper);
5070 processSync(mapper);
5071
5072 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5073 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5074 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5075 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5076 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5077 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5078 ASSERT_EQ(0, motionArgs.flags);
5079 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5080 ASSERT_EQ(0, motionArgs.buttonState);
5081 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005082 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08005083 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005084 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005085 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5086 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
5087 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5088 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5089 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5090
5091 // Should not have sent any more keys or motions.
5092 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5093 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5094}
5095
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005096TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_DoesNotRotateMotions) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005097 addConfigurationProperty("touch.deviceType", "touchScreen");
5098 prepareButtons();
5099 prepareAxes(POSITION);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005100 // InputReader works in the un-rotated coordinate space, so orientation-aware devices do not
5101 // need to be rotated. Touchscreens are orientation-aware by default.
Arpit Singha8c236b2023-04-25 13:56:05 +00005102 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005103
5104 NotifyMotionArgs args;
5105
5106 // Rotation 90.
Michael Wrighta9cf4192022-12-01 23:46:39 +00005107 prepareDisplay(ui::ROTATION_90);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005108 processDown(mapper, toRawX(50), toRawY(75));
5109 processSync(mapper);
5110
5111 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5112 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5113 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5114
5115 processUp(mapper);
5116 processSync(mapper);
5117 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5118}
5119
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005120TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_RotatesMotions) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005121 addConfigurationProperty("touch.deviceType", "touchScreen");
5122 prepareButtons();
5123 prepareAxes(POSITION);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005124 // Since InputReader works in the un-rotated coordinate space, only devices that are not
5125 // orientation-aware are affected by display rotation.
5126 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00005127 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005128
5129 NotifyMotionArgs args;
5130
5131 // Rotation 0.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005132 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005133 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005134 processDown(mapper, toRawX(50), toRawY(75));
5135 processSync(mapper);
5136
5137 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5138 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5139 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5140
5141 processUp(mapper);
5142 processSync(mapper);
5143 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5144
5145 // Rotation 90.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005146 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005147 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005148 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005149 processSync(mapper);
5150
5151 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5152 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5153 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5154
5155 processUp(mapper);
5156 processSync(mapper);
5157 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5158
5159 // Rotation 180.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005160 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005161 prepareDisplay(ui::ROTATION_180);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005162 processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
5163 processSync(mapper);
5164
5165 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5166 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5167 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5168
5169 processUp(mapper);
5170 processSync(mapper);
5171 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5172
5173 // Rotation 270.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005174 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005175 prepareDisplay(ui::ROTATION_270);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005176 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005177 processSync(mapper);
5178
5179 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5180 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5181 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5182
5183 processUp(mapper);
5184 processSync(mapper);
5185 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5186}
5187
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005188TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation0_RotatesMotions) {
5189 addConfigurationProperty("touch.deviceType", "touchScreen");
5190 prepareButtons();
5191 prepareAxes(POSITION);
5192 addConfigurationProperty("touch.orientationAware", "1");
5193 addConfigurationProperty("touch.orientation", "ORIENTATION_0");
5194 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005195 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005196 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005197 NotifyMotionArgs args;
5198
5199 // Orientation 0.
5200 processDown(mapper, toRawX(50), toRawY(75));
5201 processSync(mapper);
5202
5203 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5204 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5205 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5206
5207 processUp(mapper);
5208 processSync(mapper);
5209 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5210}
5211
5212TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation90_RotatesMotions) {
5213 addConfigurationProperty("touch.deviceType", "touchScreen");
5214 prepareButtons();
5215 prepareAxes(POSITION);
5216 addConfigurationProperty("touch.orientationAware", "1");
5217 addConfigurationProperty("touch.orientation", "ORIENTATION_90");
5218 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005219 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005220 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005221 NotifyMotionArgs args;
5222
5223 // Orientation 90.
5224 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
5225 processSync(mapper);
5226
5227 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5228 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5229 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5230
5231 processUp(mapper);
5232 processSync(mapper);
5233 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5234}
5235
5236TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation180_RotatesMotions) {
5237 addConfigurationProperty("touch.deviceType", "touchScreen");
5238 prepareButtons();
5239 prepareAxes(POSITION);
5240 addConfigurationProperty("touch.orientationAware", "1");
5241 addConfigurationProperty("touch.orientation", "ORIENTATION_180");
5242 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005243 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005244 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005245 NotifyMotionArgs args;
5246
5247 // Orientation 180.
5248 processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
5249 processSync(mapper);
5250
5251 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5252 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5253 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5254
5255 processUp(mapper);
5256 processSync(mapper);
5257 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5258}
5259
5260TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation270_RotatesMotions) {
5261 addConfigurationProperty("touch.deviceType", "touchScreen");
5262 prepareButtons();
5263 prepareAxes(POSITION);
5264 addConfigurationProperty("touch.orientationAware", "1");
5265 addConfigurationProperty("touch.orientation", "ORIENTATION_270");
5266 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005267 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005268 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005269 NotifyMotionArgs args;
5270
5271 // Orientation 270.
5272 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
5273 processSync(mapper);
5274
5275 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5276 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5277 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5278
5279 processUp(mapper);
5280 processSync(mapper);
5281 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5282}
5283
5284TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationSpecified_RotatesMotionWithDisplay) {
5285 addConfigurationProperty("touch.deviceType", "touchScreen");
5286 prepareButtons();
5287 prepareAxes(POSITION);
5288 // Since InputReader works in the un-rotated coordinate space, only devices that are not
5289 // orientation-aware are affected by display rotation.
5290 addConfigurationProperty("touch.orientationAware", "0");
5291 addConfigurationProperty("touch.orientation", "ORIENTATION_90");
Arpit Singha8c236b2023-04-25 13:56:05 +00005292 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005293
5294 NotifyMotionArgs args;
5295
5296 // Orientation 90, Rotation 0.
5297 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005298 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005299 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
5300 processSync(mapper);
5301
5302 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5303 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5304 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5305
5306 processUp(mapper);
5307 processSync(mapper);
5308 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5309
5310 // Orientation 90, Rotation 90.
5311 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005312 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005313 processDown(mapper, toRawX(50), toRawY(75));
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005314 processSync(mapper);
5315
5316 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5317 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5318 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5319
5320 processUp(mapper);
5321 processSync(mapper);
5322 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5323
5324 // Orientation 90, Rotation 180.
5325 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005326 prepareDisplay(ui::ROTATION_180);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005327 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
5328 processSync(mapper);
5329
5330 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5331 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5332 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5333
5334 processUp(mapper);
5335 processSync(mapper);
5336 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5337
5338 // Orientation 90, Rotation 270.
5339 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005340 prepareDisplay(ui::ROTATION_270);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005341 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 -07005342 processSync(mapper);
5343
5344 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5345 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5346 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5347
5348 processUp(mapper);
5349 processSync(mapper);
5350 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5351}
5352
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005353TEST_F(SingleTouchInputMapperTest, Process_IgnoresTouchesOutsidePhysicalFrame) {
5354 addConfigurationProperty("touch.deviceType", "touchScreen");
5355 prepareButtons();
5356 prepareAxes(POSITION);
5357 addConfigurationProperty("touch.orientationAware", "1");
5358 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005359 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005360
5361 // Set a physical frame in the display viewport.
5362 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
5363 viewport->physicalLeft = 20;
5364 viewport->physicalTop = 600;
5365 viewport->physicalRight = 30;
5366 viewport->physicalBottom = 610;
5367 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00005368 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005369
5370 // Start the touch.
5371 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
5372 processSync(mapper);
5373
5374 // Expect all input starting outside the physical frame to be ignored.
5375 const std::array<Point, 6> outsidePoints = {
5376 {{0, 0}, {19, 605}, {31, 605}, {25, 599}, {25, 611}, {DISPLAY_WIDTH, DISPLAY_HEIGHT}}};
5377 for (const auto& p : outsidePoints) {
5378 processMove(mapper, toRawX(p.x), toRawY(p.y));
5379 processSync(mapper);
5380 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5381 }
5382
5383 // Move the touch into the physical frame.
5384 processMove(mapper, toRawX(25), toRawY(605));
5385 processSync(mapper);
5386 NotifyMotionArgs args;
5387 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5388 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
5389 EXPECT_NEAR(25, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5390 EXPECT_NEAR(605, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5391
5392 // Once the touch down is reported, continue reporting input, even if it is outside the frame.
5393 for (const auto& p : outsidePoints) {
5394 processMove(mapper, toRawX(p.x), toRawY(p.y));
5395 processSync(mapper);
5396 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5397 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
5398 EXPECT_NEAR(p.x, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5399 EXPECT_NEAR(p.y, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5400 }
5401
5402 processUp(mapper);
5403 processSync(mapper);
5404 EXPECT_NO_FATAL_FAILURE(
5405 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
5406}
5407
Harry Cutts1db43992023-06-19 17:05:07 +00005408TEST_F(SingleTouchInputMapperTest, Process_DoesntCheckPhysicalFrameForTouchpads) {
Harry Cutts1db43992023-06-19 17:05:07 +00005409 addConfigurationProperty("touch.deviceType", "pointer");
5410 prepareAxes(POSITION);
5411 prepareDisplay(ui::ROTATION_0);
5412 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
5413
5414 // Set a physical frame in the display viewport.
5415 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
5416 viewport->physicalLeft = 20;
5417 viewport->physicalTop = 600;
5418 viewport->physicalRight = 30;
5419 viewport->physicalBottom = 610;
5420 mFakePolicy->updateViewport(*viewport);
5421 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
5422
5423 // Start the touch.
5424 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
5425 processSync(mapper);
5426
5427 // Expect all input starting outside the physical frame to result in NotifyMotionArgs being
5428 // produced.
5429 const std::array<Point, 6> outsidePoints = {
5430 {{0, 0}, {19, 605}, {31, 605}, {25, 599}, {25, 611}, {DISPLAY_WIDTH, DISPLAY_HEIGHT}}};
5431 for (const auto& p : outsidePoints) {
5432 processMove(mapper, toRawX(p.x), toRawY(p.y));
5433 processSync(mapper);
5434 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5435 }
5436}
5437
Michael Wrightd02c5b62014-02-10 15:10:22 -08005438TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005439 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005440 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005441 prepareButtons();
5442 prepareAxes(POSITION | PRESSURE | TOOL | DISTANCE | TILT);
Arpit Singha8c236b2023-04-25 13:56:05 +00005443 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005444
5445 // These calculations are based on the input device calibration documentation.
5446 int32_t rawX = 100;
5447 int32_t rawY = 200;
5448 int32_t rawPressure = 10;
5449 int32_t rawToolMajor = 12;
5450 int32_t rawDistance = 2;
5451 int32_t rawTiltX = 30;
5452 int32_t rawTiltY = 110;
5453
5454 float x = toDisplayX(rawX);
5455 float y = toDisplayY(rawY);
5456 float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
5457 float size = float(rawToolMajor) / RAW_TOOL_MAX;
5458 float tool = float(rawToolMajor) * GEOMETRIC_SCALE;
5459 float distance = float(rawDistance);
5460
5461 float tiltCenter = (RAW_TILT_MAX + RAW_TILT_MIN) * 0.5f;
5462 float tiltScale = M_PI / 180;
5463 float tiltXAngle = (rawTiltX - tiltCenter) * tiltScale;
5464 float tiltYAngle = (rawTiltY - tiltCenter) * tiltScale;
5465 float orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
5466 float tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
5467
5468 processDown(mapper, rawX, rawY);
5469 processPressure(mapper, rawPressure);
5470 processToolMajor(mapper, rawToolMajor);
5471 processDistance(mapper, rawDistance);
5472 processTilt(mapper, rawTiltX, rawTiltY);
5473 processSync(mapper);
5474
5475 NotifyMotionArgs args;
5476 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5477 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
5478 x, y, pressure, size, tool, tool, tool, tool, orientation, distance));
5479 ASSERT_EQ(tilt, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TILT));
Prabir Pradhan9a53b552024-06-04 02:59:40 +00005480 ASSERT_EQ(args.flags,
5481 AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION |
5482 AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005483}
5484
Jason Gerecke489fda82012-09-07 17:19:40 -07005485TEST_F(SingleTouchInputMapperTest, Process_XYAxes_AffineCalibration) {
Jason Gerecke489fda82012-09-07 17:19:40 -07005486 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005487 prepareDisplay(ui::ROTATION_0);
Jason Gerecke489fda82012-09-07 17:19:40 -07005488 prepareLocationCalibration();
5489 prepareButtons();
5490 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005491 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Jason Gerecke489fda82012-09-07 17:19:40 -07005492
5493 int32_t rawX = 100;
5494 int32_t rawY = 200;
5495
5496 float x = toDisplayX(toCookedX(rawX, rawY));
5497 float y = toDisplayY(toCookedY(rawX, rawY));
5498
5499 processDown(mapper, rawX, rawY);
5500 processSync(mapper);
5501
5502 NotifyMotionArgs args;
5503 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5504 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
5505 x, y, 1, 0, 0, 0, 0, 0, 0, 0));
5506}
5507
Michael Wrightd02c5b62014-02-10 15:10:22 -08005508TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllButtons) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005509 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005510 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005511 prepareButtons();
5512 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005513 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005514
5515 NotifyMotionArgs motionArgs;
5516 NotifyKeyArgs keyArgs;
5517
5518 processDown(mapper, 100, 200);
5519 processSync(mapper);
5520 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5521 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5522 ASSERT_EQ(0, motionArgs.buttonState);
5523
5524 // press BTN_LEFT, release BTN_LEFT
5525 processKey(mapper, BTN_LEFT, 1);
5526 processSync(mapper);
5527 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5528 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5529 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
5530
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005531 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5532 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5533 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
5534
Michael Wrightd02c5b62014-02-10 15:10:22 -08005535 processKey(mapper, BTN_LEFT, 0);
5536 processSync(mapper);
5537 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005538 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005539 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005540
5541 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005542 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005543 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005544
5545 // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
5546 processKey(mapper, BTN_RIGHT, 1);
5547 processKey(mapper, BTN_MIDDLE, 1);
5548 processSync(mapper);
5549 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5550 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5551 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
5552 motionArgs.buttonState);
5553
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005554 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5555 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5556 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
5557
5558 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5559 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5560 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
5561 motionArgs.buttonState);
5562
Michael Wrightd02c5b62014-02-10 15:10:22 -08005563 processKey(mapper, BTN_RIGHT, 0);
5564 processSync(mapper);
5565 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005566 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005567 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005568
5569 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005570 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005571 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005572
5573 processKey(mapper, BTN_MIDDLE, 0);
5574 processSync(mapper);
5575 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005576 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005577 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005578
5579 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005580 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005581 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005582
5583 // press BTN_BACK, release BTN_BACK
5584 processKey(mapper, BTN_BACK, 1);
5585 processSync(mapper);
5586 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5587 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5588 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005589
Michael Wrightd02c5b62014-02-10 15:10:22 -08005590 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005591 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005592 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
5593
5594 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5595 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5596 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005597
5598 processKey(mapper, BTN_BACK, 0);
5599 processSync(mapper);
5600 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005601 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005602 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005603
5604 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005605 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005606 ASSERT_EQ(0, motionArgs.buttonState);
5607
Michael Wrightd02c5b62014-02-10 15:10:22 -08005608 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5609 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5610 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
5611
5612 // press BTN_SIDE, release BTN_SIDE
5613 processKey(mapper, BTN_SIDE, 1);
5614 processSync(mapper);
5615 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5616 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5617 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005618
Michael Wrightd02c5b62014-02-10 15:10:22 -08005619 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005620 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005621 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
5622
5623 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5624 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5625 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005626
5627 processKey(mapper, BTN_SIDE, 0);
5628 processSync(mapper);
5629 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005630 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005631 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005632
5633 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005634 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005635 ASSERT_EQ(0, motionArgs.buttonState);
5636
Michael Wrightd02c5b62014-02-10 15:10:22 -08005637 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5638 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5639 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
5640
5641 // press BTN_FORWARD, release BTN_FORWARD
5642 processKey(mapper, BTN_FORWARD, 1);
5643 processSync(mapper);
5644 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5645 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5646 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005647
Michael Wrightd02c5b62014-02-10 15:10:22 -08005648 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005649 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005650 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
5651
5652 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5653 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5654 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005655
5656 processKey(mapper, BTN_FORWARD, 0);
5657 processSync(mapper);
5658 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005659 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005660 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005661
5662 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005663 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005664 ASSERT_EQ(0, motionArgs.buttonState);
5665
Michael Wrightd02c5b62014-02-10 15:10:22 -08005666 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5667 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5668 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
5669
5670 // press BTN_EXTRA, release BTN_EXTRA
5671 processKey(mapper, BTN_EXTRA, 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_FORWARD, 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_FORWARD, 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_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005684
5685 processKey(mapper, BTN_EXTRA, 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_FORWARD, keyArgs.keyCode);
5698
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005699 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5700
Michael Wrightd02c5b62014-02-10 15:10:22 -08005701 // press BTN_STYLUS, release BTN_STYLUS
5702 processKey(mapper, BTN_STYLUS, 1);
5703 processSync(mapper);
5704 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5705 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005706 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
5707
5708 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5709 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5710 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005711
5712 processKey(mapper, BTN_STYLUS, 0);
5713 processSync(mapper);
5714 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005715 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005716 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005717
5718 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005719 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005720 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005721
5722 // press BTN_STYLUS2, release BTN_STYLUS2
5723 processKey(mapper, BTN_STYLUS2, 1);
5724 processSync(mapper);
5725 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5726 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005727 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
5728
5729 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5730 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5731 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005732
5733 processKey(mapper, BTN_STYLUS2, 0);
5734 processSync(mapper);
5735 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005736 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005737 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005738
5739 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005740 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005741 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005742
5743 // release touch
5744 processUp(mapper);
5745 processSync(mapper);
5746 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5747 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5748 ASSERT_EQ(0, motionArgs.buttonState);
5749}
5750
5751TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005752 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005753 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005754 prepareButtons();
5755 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005756 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005757
5758 NotifyMotionArgs motionArgs;
5759
5760 // default tool type is finger
5761 processDown(mapper, 100, 200);
5762 processSync(mapper);
5763 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5764 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005765 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005766
5767 // eraser
5768 processKey(mapper, BTN_TOOL_RUBBER, 1);
5769 processSync(mapper);
5770 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5771 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005772 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005773
5774 // stylus
5775 processKey(mapper, BTN_TOOL_RUBBER, 0);
5776 processKey(mapper, BTN_TOOL_PEN, 1);
5777 processSync(mapper);
5778 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5779 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005780 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005781
5782 // brush
5783 processKey(mapper, BTN_TOOL_PEN, 0);
5784 processKey(mapper, BTN_TOOL_BRUSH, 1);
5785 processSync(mapper);
5786 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5787 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005788 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005789
5790 // pencil
5791 processKey(mapper, BTN_TOOL_BRUSH, 0);
5792 processKey(mapper, BTN_TOOL_PENCIL, 1);
5793 processSync(mapper);
5794 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5795 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005796 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005797
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08005798 // air-brush
Michael Wrightd02c5b62014-02-10 15:10:22 -08005799 processKey(mapper, BTN_TOOL_PENCIL, 0);
5800 processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
5801 processSync(mapper);
5802 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5803 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005804 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005805
5806 // mouse
5807 processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
5808 processKey(mapper, BTN_TOOL_MOUSE, 1);
5809 processSync(mapper);
5810 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5811 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005812 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005813
5814 // lens
5815 processKey(mapper, BTN_TOOL_MOUSE, 0);
5816 processKey(mapper, BTN_TOOL_LENS, 1);
5817 processSync(mapper);
5818 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5819 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005820 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005821
5822 // double-tap
5823 processKey(mapper, BTN_TOOL_LENS, 0);
5824 processKey(mapper, BTN_TOOL_DOUBLETAP, 1);
5825 processSync(mapper);
5826 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5827 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005828 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005829
5830 // triple-tap
5831 processKey(mapper, BTN_TOOL_DOUBLETAP, 0);
5832 processKey(mapper, BTN_TOOL_TRIPLETAP, 1);
5833 processSync(mapper);
5834 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5835 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005836 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005837
5838 // quad-tap
5839 processKey(mapper, BTN_TOOL_TRIPLETAP, 0);
5840 processKey(mapper, BTN_TOOL_QUADTAP, 1);
5841 processSync(mapper);
5842 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5843 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005844 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005845
5846 // finger
5847 processKey(mapper, BTN_TOOL_QUADTAP, 0);
5848 processKey(mapper, BTN_TOOL_FINGER, 1);
5849 processSync(mapper);
5850 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5851 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, 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 // stylus trumps finger
5855 processKey(mapper, BTN_TOOL_PEN, 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::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005860
5861 // eraser trumps stylus
5862 processKey(mapper, BTN_TOOL_RUBBER, 1);
5863 processSync(mapper);
5864 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5865 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005866 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005867
5868 // mouse trumps eraser
5869 processKey(mapper, BTN_TOOL_MOUSE, 1);
5870 processSync(mapper);
5871 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5872 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005873 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005874
5875 // back to default tool type
5876 processKey(mapper, BTN_TOOL_MOUSE, 0);
5877 processKey(mapper, BTN_TOOL_RUBBER, 0);
5878 processKey(mapper, BTN_TOOL_PEN, 0);
5879 processKey(mapper, BTN_TOOL_FINGER, 0);
5880 processSync(mapper);
5881 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5882 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005883 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005884}
5885
5886TEST_F(SingleTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005887 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005888 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005889 prepareButtons();
5890 prepareAxes(POSITION);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08005891 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_FINGER, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005892 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005893
5894 NotifyMotionArgs motionArgs;
5895
5896 // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0
5897 processKey(mapper, BTN_TOOL_FINGER, 1);
5898 processMove(mapper, 100, 200);
5899 processSync(mapper);
5900 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5901 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5902 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5903 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5904
5905 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5906 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5907 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5908 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5909
5910 // move a little
5911 processMove(mapper, 150, 250);
5912 processSync(mapper);
5913 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5914 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5915 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5916 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5917
5918 // down when BTN_TOUCH is pressed, pressure defaults to 1
5919 processKey(mapper, BTN_TOUCH, 1);
5920 processSync(mapper);
5921 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5922 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5923 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5924 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5925
5926 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5927 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5928 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5929 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5930
5931 // up when BTN_TOUCH is released, hover restored
5932 processKey(mapper, BTN_TOUCH, 0);
5933 processSync(mapper);
5934 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5935 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5936 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5937 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5938
5939 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5940 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5941 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5942 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5943
5944 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5945 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5946 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5947 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5948
5949 // exit hover when pointer goes away
5950 processKey(mapper, BTN_TOOL_FINGER, 0);
5951 processSync(mapper);
5952 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5953 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5954 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5955 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5956}
5957
5958TEST_F(SingleTouchInputMapperTest, Process_WhenAbsPressureIsPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005959 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005960 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005961 prepareButtons();
5962 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00005963 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005964
5965 NotifyMotionArgs motionArgs;
5966
5967 // initially hovering because pressure is 0
5968 processDown(mapper, 100, 200);
5969 processPressure(mapper, 0);
5970 processSync(mapper);
5971 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5972 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5973 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5974 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5975
5976 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5977 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5978 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5979 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5980
5981 // move a little
5982 processMove(mapper, 150, 250);
5983 processSync(mapper);
5984 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5985 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5986 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5987 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5988
5989 // down when pressure is non-zero
5990 processPressure(mapper, RAW_PRESSURE_MAX);
5991 processSync(mapper);
5992 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5993 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5994 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5995 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5996
5997 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5998 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5999 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6000 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
6001
6002 // up when pressure becomes 0, hover restored
6003 processPressure(mapper, 0);
6004 processSync(mapper);
6005 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6006 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
6007 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6008 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
6009
6010 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6011 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
6012 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6013 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6014
6015 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6016 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
6017 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6018 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6019
6020 // exit hover when pointer goes away
6021 processUp(mapper);
6022 processSync(mapper);
6023 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6024 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
6025 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6026 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6027}
6028
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006029TEST_F(SingleTouchInputMapperTest, Reset_CancelsOngoingGesture) {
6030 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006031 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006032 prepareButtons();
6033 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00006034 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006035
6036 // Touch down.
6037 processDown(mapper, 100, 200);
6038 processPressure(mapper, 1);
6039 processSync(mapper);
6040 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6041 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
6042
6043 // Reset the mapper. This should cancel the ongoing gesture.
6044 resetMapper(mapper, ARBITRARY_TIME);
6045 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6046 WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
6047
6048 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6049}
6050
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006051TEST_F(SingleTouchInputMapperTest, Reset_RecreatesTouchState) {
6052 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006053 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006054 prepareButtons();
6055 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00006056 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006057
6058 // Set the initial state for the touch pointer.
6059 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_X, 100);
6060 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_Y, 200);
6061 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_PRESSURE, RAW_PRESSURE_MAX);
6062 mFakeEventHub->setScanCodeState(EVENTHUB_ID, BTN_TOUCH, 1);
6063
6064 // Reset the mapper. When the mapper is reset, we expect it to attempt to recreate the touch
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006065 // state by reading the current axis values. Since there was no ongoing gesture, calling reset
6066 // does not generate any events.
6067 resetMapper(mapper, ARBITRARY_TIME);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006068
6069 // Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
6070 // the recreated touch state to generate a down event.
6071 processSync(mapper);
6072 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6073 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPressure(1.f))));
6074
6075 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6076}
6077
lilinnan687e58f2022-07-19 16:00:50 +08006078TEST_F(SingleTouchInputMapperTest,
6079 Process_WhenViewportDisplayIdChanged_TouchIsCanceledAndDeviceIsReset) {
6080 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006081 prepareDisplay(ui::ROTATION_0);
lilinnan687e58f2022-07-19 16:00:50 +08006082 prepareButtons();
6083 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006084 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
lilinnan687e58f2022-07-19 16:00:50 +08006085 NotifyMotionArgs motionArgs;
6086
6087 // Down.
Prabir Pradhan3e5ec702022-07-29 16:26:24 +00006088 processDown(mapper, 100, 200);
lilinnan687e58f2022-07-19 16:00:50 +08006089 processSync(mapper);
6090
6091 // We should receive a down event
6092 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6093 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6094
6095 // Change display id
6096 clearViewports();
6097 prepareSecondaryDisplay(ViewportType::INTERNAL);
6098
6099 // We should receive a cancel event
6100 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6101 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
6102 // Then receive reset called
6103 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6104}
6105
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006106TEST_F(SingleTouchInputMapperTest,
6107 Process_WhenViewportActiveStatusChanged_TouchIsCanceledAndDeviceIsReset) {
6108 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006109 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006110 prepareButtons();
6111 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006112 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006113 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6114 NotifyMotionArgs motionArgs;
6115
6116 // Start a new gesture.
6117 processDown(mapper, 100, 200);
6118 processSync(mapper);
6119 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6120 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6121
6122 // Make the viewport inactive. This will put the device in disabled mode.
6123 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6124 viewport->isActive = false;
6125 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006126 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006127
6128 // We should receive a cancel event for the ongoing gesture.
6129 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6130 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
6131 // Then we should be notified that the device was reset.
6132 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6133
6134 // No events are generated while the viewport is inactive.
6135 processMove(mapper, 101, 201);
6136 processSync(mapper);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006137 processUp(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006138 processSync(mapper);
6139 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6140
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006141 // Start a new gesture while the viewport is still inactive.
6142 processDown(mapper, 300, 400);
6143 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_X, 300);
6144 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_Y, 400);
6145 mFakeEventHub->setScanCodeState(EVENTHUB_ID, BTN_TOUCH, 1);
6146 processSync(mapper);
6147
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006148 // Make the viewport active again. The device should resume processing events.
6149 viewport->isActive = true;
6150 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006151 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006152
6153 // The device is reset because it changes back to direct mode, without generating any events.
6154 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6155 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6156
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006157 // In the next sync, the touch state that was recreated when the device was reset is reported.
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006158 processSync(mapper);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006159 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6160 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006161
6162 // No more events.
6163 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6164 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
6165}
6166
Prabir Pradhan211ba622022-10-31 21:09:21 +00006167TEST_F(SingleTouchInputMapperTest, ButtonIsReleasedOnTouchUp) {
6168 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006169 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan211ba622022-10-31 21:09:21 +00006170 prepareButtons();
6171 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006172 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan211ba622022-10-31 21:09:21 +00006173 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6174
6175 // Press a stylus button.
6176 processKey(mapper, BTN_STYLUS, 1);
6177 processSync(mapper);
6178
6179 // Start a touch gesture and ensure the BUTTON_PRESS event is generated.
6180 processDown(mapper, 100, 200);
6181 processSync(mapper);
6182 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6183 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6184 WithCoords(toDisplayX(100), toDisplayY(200)),
6185 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6186 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6187 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
6188 WithCoords(toDisplayX(100), toDisplayY(200)),
6189 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6190
6191 // Release the touch gesture. Ensure that the BUTTON_RELEASE event is generated even though
6192 // the button has not actually been released, since there will be no pointers through which the
6193 // button state can be reported. The event is generated at the location of the pointer before
6194 // it went up.
6195 processUp(mapper);
6196 processSync(mapper);
6197 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6198 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
6199 WithCoords(toDisplayX(100), toDisplayY(200)), WithButtonState(0))));
6200 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6201 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6202 WithCoords(toDisplayX(100), toDisplayY(200)), WithButtonState(0))));
6203}
6204
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00006205TEST_F(SingleTouchInputMapperTest, StylusButtonMotionEventsDisabled) {
6206 addConfigurationProperty("touch.deviceType", "touchScreen");
6207 prepareDisplay(ui::ROTATION_0);
6208 prepareButtons();
6209 prepareAxes(POSITION);
6210
6211 mFakePolicy->setStylusButtonMotionEventsEnabled(false);
6212
Arpit Singha8c236b2023-04-25 13:56:05 +00006213 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00006214 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6215
6216 // Press a stylus button.
6217 processKey(mapper, BTN_STYLUS, 1);
6218 processSync(mapper);
6219
6220 // Start a touch gesture and ensure that the stylus button is not reported.
6221 processDown(mapper, 100, 200);
6222 processSync(mapper);
6223 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6224 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithButtonState(0))));
6225
6226 // Release and press the stylus button again.
6227 processKey(mapper, BTN_STYLUS, 0);
6228 processSync(mapper);
6229 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6230 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
6231 processKey(mapper, BTN_STYLUS, 1);
6232 processSync(mapper);
6233 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6234 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
6235
6236 // Release the touch gesture.
6237 processUp(mapper);
6238 processSync(mapper);
6239 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6240 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
6241
6242 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6243}
6244
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006245TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsSetToTouchNavigation_setsCorrectType) {
6246 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
6247 prepareDisplay(ui::ROTATION_0);
6248 prepareButtons();
6249 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006250 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006251 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6252
Prabir Pradhan9cf8f322024-06-18 20:22:42 +00006253 ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION | AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006254}
6255
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006256TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsChangedToTouchNavigation_updatesDeviceType) {
6257 // Initialize the device without setting device source to touch navigation.
6258 addConfigurationProperty("touch.deviceType", "touchScreen");
6259 prepareDisplay(ui::ROTATION_0);
6260 prepareButtons();
6261 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006262 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006263
6264 // Ensure that the device is created as a touchscreen, not touch navigation.
6265 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
6266
6267 // Add device type association after the device was created.
6268 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
6269
6270 // Send update to the mapper.
6271 std::list<NotifyArgs> unused2 =
6272 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006273 InputReaderConfiguration::Change::DEVICE_TYPE /*changes*/);
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006274
6275 // Check whether device type update was successful.
Prabir Pradhan9cf8f322024-06-18 20:22:42 +00006276 ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION | AINPUT_SOURCE_TOUCHPAD, mDevice->getSources());
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006277}
6278
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006279TEST_F(SingleTouchInputMapperTest, HoverEventsOutsidePhysicalFrameAreIgnored) {
6280 // Initialize the device without setting device source to touch navigation.
6281 addConfigurationProperty("touch.deviceType", "touchScreen");
6282 prepareDisplay(ui::ROTATION_0);
6283 prepareButtons();
6284 prepareAxes(POSITION);
6285 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
6286
6287 // Set a physical frame in the display viewport.
6288 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6289 viewport->physicalLeft = 0;
6290 viewport->physicalTop = 0;
6291 viewport->physicalRight = DISPLAY_WIDTH / 2;
6292 viewport->physicalBottom = DISPLAY_HEIGHT / 2;
6293 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006294 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006295
Arpit Singha8c236b2023-04-25 13:56:05 +00006296 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006297
6298 // Hovering inside the physical frame produces events.
6299 processKey(mapper, BTN_TOOL_PEN, 1);
6300 processMove(mapper, RAW_X_MIN + 1, RAW_Y_MIN + 1);
6301 processSync(mapper);
6302 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6303 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)));
6304 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6305 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)));
6306
6307 // Leaving the physical frame ends the hovering gesture.
6308 processMove(mapper, RAW_X_MAX - 1, RAW_Y_MAX - 1);
6309 processSync(mapper);
6310 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6311 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT)));
6312
6313 // Moving outside the physical frame does not produce events.
6314 processMove(mapper, RAW_X_MAX - 2, RAW_Y_MAX - 2);
6315 processSync(mapper);
6316 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6317
6318 // Re-entering the physical frame produces events.
6319 processMove(mapper, RAW_X_MIN, RAW_Y_MIN);
6320 processSync(mapper);
6321 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6322 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)));
6323 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6324 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)));
6325}
6326
Prabir Pradhan5632d622021-09-06 07:57:20 -07006327// --- TouchDisplayProjectionTest ---
6328
6329class TouchDisplayProjectionTest : public SingleTouchInputMapperTest {
6330public:
6331 // The values inside DisplayViewport are expected to be pre-rotated. This updates the current
6332 // DisplayViewport to pre-rotate the values. The viewport's physical display will be set to the
6333 // rotated equivalent of the given un-rotated physical display bounds.
Prabir Pradhana9df3162022-12-05 23:57:27 +00006334 void configurePhysicalDisplay(ui::Rotation orientation, Rect naturalPhysicalDisplay,
6335 int32_t naturalDisplayWidth = DISPLAY_WIDTH,
6336 int32_t naturalDisplayHeight = DISPLAY_HEIGHT) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006337 uint32_t inverseRotationFlags;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006338 auto rotatedWidth = naturalDisplayWidth;
6339 auto rotatedHeight = naturalDisplayHeight;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006340 switch (orientation) {
Michael Wrighta9cf4192022-12-01 23:46:39 +00006341 case ui::ROTATION_90:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006342 inverseRotationFlags = ui::Transform::ROT_270;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006343 std::swap(rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006344 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006345 case ui::ROTATION_180:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006346 inverseRotationFlags = ui::Transform::ROT_180;
6347 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006348 case ui::ROTATION_270:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006349 inverseRotationFlags = ui::Transform::ROT_90;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006350 std::swap(rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006351 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006352 case ui::ROTATION_0:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006353 inverseRotationFlags = ui::Transform::ROT_0;
6354 break;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006355 }
6356
Prabir Pradhana9df3162022-12-05 23:57:27 +00006357 const ui::Transform rotation(inverseRotationFlags, rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006358 const Rect rotatedPhysicalDisplay = rotation.transform(naturalPhysicalDisplay);
6359
6360 std::optional<DisplayViewport> internalViewport =
6361 *mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6362 DisplayViewport& v = *internalViewport;
6363 v.displayId = DISPLAY_ID;
6364 v.orientation = orientation;
6365
6366 v.logicalLeft = 0;
6367 v.logicalTop = 0;
6368 v.logicalRight = 100;
6369 v.logicalBottom = 100;
6370
6371 v.physicalLeft = rotatedPhysicalDisplay.left;
6372 v.physicalTop = rotatedPhysicalDisplay.top;
6373 v.physicalRight = rotatedPhysicalDisplay.right;
6374 v.physicalBottom = rotatedPhysicalDisplay.bottom;
6375
Prabir Pradhana9df3162022-12-05 23:57:27 +00006376 v.deviceWidth = rotatedWidth;
6377 v.deviceHeight = rotatedHeight;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006378
6379 v.isActive = true;
6380 v.uniqueId = UNIQUE_ID;
6381 v.type = ViewportType::INTERNAL;
6382 mFakePolicy->updateViewport(v);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006383 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006384 }
6385
6386 void assertReceivedMove(const Point& point) {
6387 NotifyMotionArgs motionArgs;
6388 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6389 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006390 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Prabir Pradhan5632d622021-09-06 07:57:20 -07006391 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], point.x, point.y,
6392 1, 0, 0, 0, 0, 0, 0, 0));
6393 }
6394};
6395
6396TEST_F(TouchDisplayProjectionTest, IgnoresTouchesOutsidePhysicalDisplay) {
6397 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006398 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006399
6400 prepareButtons();
6401 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006402 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan5632d622021-09-06 07:57:20 -07006403
6404 NotifyMotionArgs motionArgs;
6405
6406 // Configure the DisplayViewport such that the logical display maps to a subsection of
6407 // the display panel called the physical display. Here, the physical display is bounded by the
6408 // points (10, 20) and (70, 160) inside the display space, which is of the size 400 x 800.
6409 static const Rect kPhysicalDisplay{10, 20, 70, 160};
6410 static const std::array<Point, 6> kPointsOutsidePhysicalDisplay{
6411 {{-10, -10}, {0, 0}, {5, 100}, {50, 15}, {75, 100}, {50, 165}}};
6412
Michael Wrighta9cf4192022-12-01 23:46:39 +00006413 for (auto orientation : {ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180, ui::ROTATION_270}) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006414 configurePhysicalDisplay(orientation, kPhysicalDisplay);
6415
6416 // Touches outside the physical display should be ignored, and should not generate any
6417 // events. Ensure touches at the following points that lie outside of the physical display
6418 // area do not generate any events.
6419 for (const auto& point : kPointsOutsidePhysicalDisplay) {
6420 processDown(mapper, toRawX(point.x), toRawY(point.y));
6421 processSync(mapper);
6422 processUp(mapper);
6423 processSync(mapper);
6424 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled())
6425 << "Unexpected event generated for touch outside physical display at point: "
6426 << point.x << ", " << point.y;
6427 }
6428 }
6429}
6430
6431TEST_F(TouchDisplayProjectionTest, EmitsTouchDownAfterEnteringPhysicalDisplay) {
6432 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006433 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006434
6435 prepareButtons();
6436 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006437 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan5632d622021-09-06 07:57:20 -07006438
6439 NotifyMotionArgs motionArgs;
6440
6441 // Configure the DisplayViewport such that the logical display maps to a subsection of
6442 // the display panel called the physical display. Here, the physical display is bounded by the
6443 // points (10, 20) and (70, 160) inside the display space, which is of the size 400 x 800.
6444 static const Rect kPhysicalDisplay{10, 20, 70, 160};
6445
Michael Wrighta9cf4192022-12-01 23:46:39 +00006446 for (auto orientation : {ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180, ui::ROTATION_270}) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006447 configurePhysicalDisplay(orientation, kPhysicalDisplay);
6448
6449 // Touches that start outside the physical display should be ignored until it enters the
6450 // physical display bounds, at which point it should generate a down event. Start a touch at
6451 // the point (5, 100), which is outside the physical display bounds.
6452 static const Point kOutsidePoint{5, 100};
6453 processDown(mapper, toRawX(kOutsidePoint.x), toRawY(kOutsidePoint.y));
6454 processSync(mapper);
6455 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6456
6457 // Move the touch into the physical display area. This should generate a pointer down.
6458 processMove(mapper, toRawX(11), toRawY(21));
6459 processSync(mapper);
6460 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6461 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006462 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Prabir Pradhan5632d622021-09-06 07:57:20 -07006463 ASSERT_NO_FATAL_FAILURE(
6464 assertPointerCoords(motionArgs.pointerCoords[0], 11, 21, 1, 0, 0, 0, 0, 0, 0, 0));
6465
6466 // Move the touch inside the physical display area. This should generate a pointer move.
6467 processMove(mapper, toRawX(69), toRawY(159));
6468 processSync(mapper);
6469 assertReceivedMove({69, 159});
6470
6471 // Move outside the physical display area. Since the pointer is already down, this should
6472 // now continue generating events.
6473 processMove(mapper, toRawX(kOutsidePoint.x), toRawY(kOutsidePoint.y));
6474 processSync(mapper);
6475 assertReceivedMove(kOutsidePoint);
6476
6477 // Release. This should generate a pointer up.
6478 processUp(mapper);
6479 processSync(mapper);
6480 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6481 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
6482 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], kOutsidePoint.x,
6483 kOutsidePoint.y, 1, 0, 0, 0, 0, 0, 0, 0));
6484
6485 // Ensure no more events were generated.
6486 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
6487 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6488 }
6489}
6490
Prabir Pradhana9df3162022-12-05 23:57:27 +00006491// --- TouchscreenPrecisionTests ---
6492
6493// This test suite is used to ensure that touchscreen devices are scaled and configured correctly
6494// in various orientations and with different display rotations. We configure the touchscreen to
6495// have a higher resolution than that of the display by an integer scale factor in each axis so that
6496// we can enforce that coordinates match precisely as expected.
6497class TouchscreenPrecisionTestsFixture : public TouchDisplayProjectionTest,
6498 public ::testing::WithParamInterface<ui::Rotation> {
6499public:
6500 void SetUp() override {
6501 SingleTouchInputMapperTest::SetUp();
6502
6503 // Prepare the raw axes to have twice the resolution of the display in the X axis and
6504 // four times the resolution of the display in the Y axis.
6505 prepareButtons();
6506 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, PRECISION_RAW_X_MIN, PRECISION_RAW_X_MAX,
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006507 PRECISION_RAW_X_FLAT, PRECISION_RAW_X_FUZZ,
6508 PRECISION_RAW_X_RES);
Prabir Pradhana9df3162022-12-05 23:57:27 +00006509 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, PRECISION_RAW_Y_MIN, PRECISION_RAW_Y_MAX,
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006510 PRECISION_RAW_Y_FLAT, PRECISION_RAW_Y_FUZZ,
6511 PRECISION_RAW_Y_RES);
Prabir Pradhana9df3162022-12-05 23:57:27 +00006512 }
6513
6514 static const int32_t PRECISION_RAW_X_MIN = TouchInputMapperTest::RAW_X_MIN;
6515 static const int32_t PRECISION_RAW_X_MAX = PRECISION_RAW_X_MIN + DISPLAY_WIDTH * 2 - 1;
6516 static const int32_t PRECISION_RAW_Y_MIN = TouchInputMapperTest::RAW_Y_MIN;
6517 static const int32_t PRECISION_RAW_Y_MAX = PRECISION_RAW_Y_MIN + DISPLAY_HEIGHT * 4 - 1;
6518
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006519 static const int32_t PRECISION_RAW_X_RES = 50; // units per millimeter
6520 static const int32_t PRECISION_RAW_Y_RES = 100; // units per millimeter
6521
6522 static const int32_t PRECISION_RAW_X_FLAT = 16;
6523 static const int32_t PRECISION_RAW_Y_FLAT = 32;
6524
6525 static const int32_t PRECISION_RAW_X_FUZZ = 4;
6526 static const int32_t PRECISION_RAW_Y_FUZZ = 8;
6527
Prabir Pradhana9df3162022-12-05 23:57:27 +00006528 static const std::array<Point, 4> kRawCorners;
6529};
6530
6531const std::array<Point, 4> TouchscreenPrecisionTestsFixture::kRawCorners = {{
6532 {PRECISION_RAW_X_MIN, PRECISION_RAW_Y_MIN}, // left-top
6533 {PRECISION_RAW_X_MAX, PRECISION_RAW_Y_MIN}, // right-top
6534 {PRECISION_RAW_X_MAX, PRECISION_RAW_Y_MAX}, // right-bottom
6535 {PRECISION_RAW_X_MIN, PRECISION_RAW_Y_MAX}, // left-bottom
6536}};
6537
6538// Tests for how the touchscreen is oriented relative to the natural orientation of the display.
6539// For example, if a touchscreen is configured with an orientation of 90 degrees, it is a portrait
6540// touchscreen panel that is used on a device whose natural display orientation is in landscape.
6541TEST_P(TouchscreenPrecisionTestsFixture, OrientationPrecision) {
6542 enum class Orientation {
6543 ORIENTATION_0 = ui::toRotationInt(ui::ROTATION_0),
6544 ORIENTATION_90 = ui::toRotationInt(ui::ROTATION_90),
6545 ORIENTATION_180 = ui::toRotationInt(ui::ROTATION_180),
6546 ORIENTATION_270 = ui::toRotationInt(ui::ROTATION_270),
6547 ftl_last = ORIENTATION_270,
6548 };
6549 using Orientation::ORIENTATION_0, Orientation::ORIENTATION_90, Orientation::ORIENTATION_180,
6550 Orientation::ORIENTATION_270;
6551 static const std::map<Orientation, std::array<vec2, 4> /*mappedCorners*/> kMappedCorners = {
6552 {ORIENTATION_0, {{{0, 0}, {479.5, 0}, {479.5, 799.75}, {0, 799.75}}}},
6553 {ORIENTATION_90, {{{0, 479.5}, {0, 0}, {799.75, 0}, {799.75, 479.5}}}},
6554 {ORIENTATION_180, {{{479.5, 799.75}, {0, 799.75}, {0, 0}, {479.5, 0}}}},
6555 {ORIENTATION_270, {{{799.75, 0}, {799.75, 479.5}, {0, 479.5}, {0, 0}}}},
6556 };
6557
6558 const auto touchscreenOrientation = static_cast<Orientation>(ui::toRotationInt(GetParam()));
6559
6560 // Configure the touchscreen as being installed in the one of the four different orientations
6561 // relative to the display.
6562 addConfigurationProperty("touch.deviceType", "touchScreen");
6563 addConfigurationProperty("touch.orientation", ftl::enum_string(touchscreenOrientation).c_str());
6564 prepareDisplay(ui::ROTATION_0);
6565
Arpit Singha8c236b2023-04-25 13:56:05 +00006566 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhana9df3162022-12-05 23:57:27 +00006567
6568 // If the touchscreen is installed in a rotated orientation relative to the display (i.e. in
6569 // orientations of either 90 or 270) this means the display's natural resolution will be
6570 // flipped.
6571 const bool displayRotated =
6572 touchscreenOrientation == ORIENTATION_90 || touchscreenOrientation == ORIENTATION_270;
6573 const int32_t width = displayRotated ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
6574 const int32_t height = displayRotated ? DISPLAY_WIDTH : DISPLAY_HEIGHT;
6575 const Rect physicalFrame{0, 0, width, height};
6576 configurePhysicalDisplay(ui::ROTATION_0, physicalFrame, width, height);
6577
6578 const auto& expectedPoints = kMappedCorners.at(touchscreenOrientation);
6579 const float expectedPrecisionX = displayRotated ? 4 : 2;
6580 const float expectedPrecisionY = displayRotated ? 2 : 4;
6581
6582 // Test all four corners.
6583 for (int i = 0; i < 4; i++) {
6584 const auto& raw = kRawCorners[i];
6585 processDown(mapper, raw.x, raw.y);
6586 processSync(mapper);
6587 const auto& expected = expectedPoints[i];
6588 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6589 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6590 WithCoords(expected.x, expected.y),
6591 WithPrecision(expectedPrecisionX, expectedPrecisionY))))
6592 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6593 << "with touchscreen orientation "
6594 << ftl::enum_string(touchscreenOrientation).c_str() << ", expected point ("
6595 << expected.x << ", " << expected.y << ").";
6596 processUp(mapper);
6597 processSync(mapper);
6598 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6599 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6600 WithCoords(expected.x, expected.y))));
6601 }
6602}
6603
Prabir Pradhan82687402022-12-06 01:32:53 +00006604TEST_P(TouchscreenPrecisionTestsFixture, RotationPrecisionWhenOrientationAware) {
6605 static const std::map<ui::Rotation /*rotation*/, std::array<vec2, 4> /*mappedCorners*/>
6606 kMappedCorners = {
6607 {ui::ROTATION_0, {{{0, 0}, {479.5, 0}, {479.5, 799.75}, {0, 799.75}}}},
6608 {ui::ROTATION_90, {{{0.5, 0}, {480, 0}, {480, 799.75}, {0.5, 799.75}}}},
6609 {ui::ROTATION_180, {{{0.5, 0.25}, {480, 0.25}, {480, 800}, {0.5, 800}}}},
6610 {ui::ROTATION_270, {{{0, 0.25}, {479.5, 0.25}, {479.5, 800}, {0, 800}}}},
6611 };
6612
6613 const ui::Rotation displayRotation = GetParam();
6614
6615 addConfigurationProperty("touch.deviceType", "touchScreen");
6616 prepareDisplay(displayRotation);
6617
Arpit Singha8c236b2023-04-25 13:56:05 +00006618 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan82687402022-12-06 01:32:53 +00006619
6620 const auto& expectedPoints = kMappedCorners.at(displayRotation);
6621
6622 // Test all four corners.
6623 for (int i = 0; i < 4; i++) {
6624 const auto& expected = expectedPoints[i];
6625 const auto& raw = kRawCorners[i];
6626 processDown(mapper, raw.x, raw.y);
6627 processSync(mapper);
6628 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6629 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6630 WithCoords(expected.x, expected.y), WithPrecision(2, 4))))
6631 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6632 << "with display rotation " << ui::toCString(displayRotation)
6633 << ", expected point (" << expected.x << ", " << expected.y << ").";
6634 processUp(mapper);
6635 processSync(mapper);
6636 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6637 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6638 WithCoords(expected.x, expected.y))));
6639 }
6640}
6641
Prabir Pradhan3e798762022-12-02 21:02:11 +00006642TEST_P(TouchscreenPrecisionTestsFixture, RotationPrecisionOrientationAwareInOri270) {
6643 static const std::map<ui::Rotation /*orientation*/, std::array<vec2, 4> /*mappedCorners*/>
6644 kMappedCorners = {
6645 {ui::ROTATION_0, {{{799.75, 0}, {799.75, 479.5}, {0, 479.5}, {0, 0}}}},
6646 {ui::ROTATION_90, {{{800, 0}, {800, 479.5}, {0.25, 479.5}, {0.25, 0}}}},
6647 {ui::ROTATION_180, {{{800, 0.5}, {800, 480}, {0.25, 480}, {0.25, 0.5}}}},
6648 {ui::ROTATION_270, {{{799.75, 0.5}, {799.75, 480}, {0, 480}, {0, 0.5}}}},
6649 };
6650
6651 const ui::Rotation displayRotation = GetParam();
6652
6653 addConfigurationProperty("touch.deviceType", "touchScreen");
6654 addConfigurationProperty("touch.orientation", "ORIENTATION_270");
6655
Arpit Singha8c236b2023-04-25 13:56:05 +00006656 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan3e798762022-12-02 21:02:11 +00006657
6658 // Ori 270, so width and height swapped
6659 const Rect physicalFrame{0, 0, DISPLAY_HEIGHT, DISPLAY_WIDTH};
6660 prepareDisplay(displayRotation);
6661 configurePhysicalDisplay(displayRotation, physicalFrame, DISPLAY_HEIGHT, DISPLAY_WIDTH);
6662
6663 const auto& expectedPoints = kMappedCorners.at(displayRotation);
6664
6665 // Test all four corners.
6666 for (int i = 0; i < 4; i++) {
6667 const auto& expected = expectedPoints[i];
6668 const auto& raw = kRawCorners[i];
6669 processDown(mapper, raw.x, raw.y);
6670 processSync(mapper);
6671 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6672 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6673 WithCoords(expected.x, expected.y), WithPrecision(4, 2))))
6674 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6675 << "with display rotation " << ui::toCString(displayRotation)
6676 << ", expected point (" << expected.x << ", " << expected.y << ").";
6677 processUp(mapper);
6678 processSync(mapper);
6679 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6680 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6681 WithCoords(expected.x, expected.y))));
6682 }
6683}
6684
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006685TEST_P(TouchscreenPrecisionTestsFixture, MotionRangesAreOrientedInRotatedDisplay) {
6686 const ui::Rotation displayRotation = GetParam();
6687
6688 addConfigurationProperty("touch.deviceType", "touchScreen");
6689 prepareDisplay(displayRotation);
6690
6691 __attribute__((unused)) SingleTouchInputMapper& mapper =
Arpit Singha8c236b2023-04-25 13:56:05 +00006692 constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006693
6694 const InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
6695 // MotionRanges use display pixels as their units
6696 const auto* xRange = deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHSCREEN);
6697 const auto* yRange = deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_Y, AINPUT_SOURCE_TOUCHSCREEN);
6698
6699 // The MotionRanges should be oriented in the rotated display's coordinate space
6700 const bool displayRotated =
6701 displayRotation == ui::ROTATION_90 || displayRotation == ui::ROTATION_270;
6702
6703 constexpr float MAX_X = 479.5;
6704 constexpr float MAX_Y = 799.75;
6705 EXPECT_EQ(xRange->min, 0.f);
6706 EXPECT_EQ(yRange->min, 0.f);
6707 EXPECT_EQ(xRange->max, displayRotated ? MAX_Y : MAX_X);
6708 EXPECT_EQ(yRange->max, displayRotated ? MAX_X : MAX_Y);
6709
6710 EXPECT_EQ(xRange->flat, 8.f);
6711 EXPECT_EQ(yRange->flat, 8.f);
6712
6713 EXPECT_EQ(xRange->fuzz, 2.f);
6714 EXPECT_EQ(yRange->fuzz, 2.f);
6715
6716 EXPECT_EQ(xRange->resolution, 25.f); // pixels per millimeter
6717 EXPECT_EQ(yRange->resolution, 25.f); // pixels per millimeter
6718}
6719
Prabir Pradhana9df3162022-12-05 23:57:27 +00006720// Run the precision tests for all rotations.
6721INSTANTIATE_TEST_SUITE_P(TouchscreenPrecisionTests, TouchscreenPrecisionTestsFixture,
6722 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
6723 ui::ROTATION_270),
6724 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
6725 return ftl::enum_string(testParamInfo.param);
6726 });
6727
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006728// --- ExternalStylusFusionTest ---
6729
6730class ExternalStylusFusionTest : public SingleTouchInputMapperTest {
6731public:
6732 SingleTouchInputMapper& initializeInputMapperWithExternalStylus() {
6733 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006734 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006735 prepareButtons();
6736 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006737 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006738
6739 mStylusState.when = ARBITRARY_TIME;
6740 mStylusState.pressure = 0.f;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006741 mStylusState.toolType = ToolType::STYLUS;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006742 mReader->getContext()->setExternalStylusDevices({mExternalStylusDeviceInfo});
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006743 configureDevice(InputReaderConfiguration::Change::EXTERNAL_STYLUS_PRESENCE);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006744 processExternalStylusState(mapper);
6745 return mapper;
6746 }
6747
6748 std::list<NotifyArgs> processExternalStylusState(InputMapper& mapper) {
6749 std::list<NotifyArgs> generatedArgs = mapper.updateExternalStylusState(mStylusState);
6750 for (const NotifyArgs& args : generatedArgs) {
6751 mFakeListener->notify(args);
6752 }
6753 // Loop the reader to flush the input listener queue.
6754 mReader->loopOnce();
6755 return generatedArgs;
6756 }
6757
6758protected:
6759 StylusState mStylusState{};
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006760
6761 void testStartFusedStylusGesture(SingleTouchInputMapper& mapper) {
6762 auto toolTypeSource =
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006763 AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006764
6765 // The first pointer is withheld.
6766 processDown(mapper, 100, 200);
6767 processSync(mapper);
6768 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6769 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6770 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6771
6772 // The external stylus reports pressure. The withheld finger pointer is released as a
6773 // stylus.
6774 mStylusState.pressure = 1.f;
6775 processExternalStylusState(mapper);
6776 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6777 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6778 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6779
6780 // Subsequent pointer events are not withheld.
6781 processMove(mapper, 101, 201);
6782 processSync(mapper);
6783 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6784 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6785
6786 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6787 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6788 }
6789
6790 void testSuccessfulFusionGesture(SingleTouchInputMapper& mapper) {
6791 ASSERT_NO_FATAL_FAILURE(testStartFusedStylusGesture(mapper));
6792
6793 // Releasing the touch pointer ends the gesture.
6794 processUp(mapper);
6795 processSync(mapper);
6796 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006797 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(STYLUS_FUSION_SOURCE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006798 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006799
6800 mStylusState.pressure = 0.f;
6801 processExternalStylusState(mapper);
6802 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6803 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6804 }
6805
6806 void testUnsuccessfulFusionGesture(SingleTouchInputMapper& mapper) {
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006807 // When stylus fusion is not successful, events should be reported with the original source.
6808 // In this case, it is from a touchscreen.
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006809 auto toolTypeSource =
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006810 AllOf(WithSource(AINPUT_SOURCE_TOUCHSCREEN), WithToolType(ToolType::FINGER));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006811
6812 // The first pointer is withheld when an external stylus is connected,
6813 // and a timeout is requested.
6814 processDown(mapper, 100, 200);
6815 processSync(mapper);
6816 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6817 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6818 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6819
6820 // If the timeout expires early, it is requested again.
6821 handleTimeout(mapper, ARBITRARY_TIME + 1);
6822 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6823 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6824
6825 // When the timeout expires, the withheld touch is released as a finger pointer.
6826 handleTimeout(mapper, ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT);
6827 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6828 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6829
6830 // Subsequent pointer events are not withheld.
6831 processMove(mapper, 101, 201);
6832 processSync(mapper);
6833 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6834 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6835 processUp(mapper);
6836 processSync(mapper);
6837 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6838 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP))));
6839
6840 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6841 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6842 }
6843
6844private:
6845 InputDeviceInfo mExternalStylusDeviceInfo{};
6846};
6847
6848TEST_F(ExternalStylusFusionTest, UsesBluetoothStylusSource) {
6849 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006850 ASSERT_EQ(STYLUS_FUSION_SOURCE, mapper.getSources());
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006851}
6852
6853TEST_F(ExternalStylusFusionTest, UnsuccessfulFusion) {
6854 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6855 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6856}
6857
6858TEST_F(ExternalStylusFusionTest, SuccessfulFusion_TouchFirst) {
6859 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6860 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6861}
6862
6863// Test a successful stylus fusion gesture where the pressure is reported by the external
6864// before the touch is reported by the touchscreen.
6865TEST_F(ExternalStylusFusionTest, SuccessfulFusion_PressureFirst) {
6866 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006867 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006868
6869 // The external stylus reports pressure first. It is ignored for now.
6870 mStylusState.pressure = 1.f;
6871 processExternalStylusState(mapper);
6872 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6873 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6874
6875 // When the touch goes down afterwards, it is reported as a stylus pointer.
6876 processDown(mapper, 100, 200);
6877 processSync(mapper);
6878 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6879 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6880 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6881
6882 processMove(mapper, 101, 201);
6883 processSync(mapper);
6884 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6885 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6886 processUp(mapper);
6887 processSync(mapper);
6888 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6889 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP))));
6890
6891 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6892 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6893}
6894
6895TEST_F(ExternalStylusFusionTest, FusionIsRepeatedForEachNewGesture) {
6896 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6897
6898 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6899 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6900
6901 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6902 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6903 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6904 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6905}
6906
6907TEST_F(ExternalStylusFusionTest, FusedPointerReportsPressureChanges) {
6908 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006909 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006910
6911 mStylusState.pressure = 0.8f;
6912 processExternalStylusState(mapper);
6913 processDown(mapper, 100, 200);
6914 processSync(mapper);
6915 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6916 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6917 WithPressure(0.8f))));
6918 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6919
6920 // The external stylus reports a pressure change. We wait for some time for a touch event.
6921 mStylusState.pressure = 0.6f;
6922 processExternalStylusState(mapper);
6923 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6924 ASSERT_NO_FATAL_FAILURE(
6925 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6926
6927 // If a touch is reported within the timeout, it reports the updated pressure.
6928 processMove(mapper, 101, 201);
6929 processSync(mapper);
6930 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6931 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6932 WithPressure(0.6f))));
6933 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6934
6935 // There is another pressure change.
6936 mStylusState.pressure = 0.5f;
6937 processExternalStylusState(mapper);
6938 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6939 ASSERT_NO_FATAL_FAILURE(
6940 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6941
6942 // If a touch is not reported within the timeout, a move event is generated to report
6943 // the new pressure.
6944 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
6945 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6946 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6947 WithPressure(0.5f))));
6948
6949 // If a zero pressure is reported before the touch goes up, the previous pressure value is
6950 // repeated indefinitely.
6951 mStylusState.pressure = 0.0f;
6952 processExternalStylusState(mapper);
6953 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6954 ASSERT_NO_FATAL_FAILURE(
6955 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6956 processMove(mapper, 102, 202);
6957 processSync(mapper);
6958 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6959 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6960 WithPressure(0.5f))));
6961 processMove(mapper, 103, 203);
6962 processSync(mapper);
6963 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6964 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6965 WithPressure(0.5f))));
6966
6967 processUp(mapper);
6968 processSync(mapper);
6969 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006970 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(STYLUS_FUSION_SOURCE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006971 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006972
6973 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6974 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6975}
6976
6977TEST_F(ExternalStylusFusionTest, FusedPointerReportsToolTypeChanges) {
6978 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006979 auto source = WithSource(STYLUS_FUSION_SOURCE);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006980
6981 mStylusState.pressure = 1.f;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006982 mStylusState.toolType = ToolType::ERASER;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006983 processExternalStylusState(mapper);
6984 processDown(mapper, 100, 200);
6985 processSync(mapper);
6986 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6987 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006988 WithToolType(ToolType::ERASER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006989 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6990
6991 // The external stylus reports a tool change. We wait for some time for a touch event.
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006992 mStylusState.toolType = ToolType::STYLUS;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006993 processExternalStylusState(mapper);
6994 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6995 ASSERT_NO_FATAL_FAILURE(
6996 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6997
6998 // If a touch is reported within the timeout, it reports the updated pressure.
6999 processMove(mapper, 101, 201);
7000 processSync(mapper);
7001 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7002 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007003 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007004 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7005
7006 // There is another tool type change.
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007007 mStylusState.toolType = ToolType::FINGER;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007008 processExternalStylusState(mapper);
7009 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7010 ASSERT_NO_FATAL_FAILURE(
7011 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7012
7013 // If a touch is not reported within the timeout, a move event is generated to report
7014 // the new tool type.
7015 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
7016 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7017 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007018 WithToolType(ToolType::FINGER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007019
7020 processUp(mapper);
7021 processSync(mapper);
7022 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7023 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007024 WithToolType(ToolType::FINGER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007025
7026 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7027 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7028}
7029
7030TEST_F(ExternalStylusFusionTest, FusedPointerReportsButtons) {
7031 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00007032 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007033
7034 ASSERT_NO_FATAL_FAILURE(testStartFusedStylusGesture(mapper));
7035
7036 // The external stylus reports a button change. We wait for some time for a touch event.
7037 mStylusState.buttons = AMOTION_EVENT_BUTTON_STYLUS_PRIMARY;
7038 processExternalStylusState(mapper);
7039 ASSERT_NO_FATAL_FAILURE(
7040 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7041
7042 // If a touch is reported within the timeout, it reports the updated button state.
7043 processMove(mapper, 101, 201);
7044 processSync(mapper);
7045 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7046 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
7047 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
7048 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7049 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
7050 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
7051 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7052
7053 // The button is now released.
7054 mStylusState.buttons = 0;
7055 processExternalStylusState(mapper);
7056 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7057 ASSERT_NO_FATAL_FAILURE(
7058 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7059
7060 // If a touch is not reported within the timeout, a move event is generated to report
7061 // the new button state.
7062 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007063 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7064 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
7065 WithButtonState(0))));
7066 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhan124ea442022-10-28 20:27:44 +00007067 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
7068 WithButtonState(0))));
7069
7070 processUp(mapper);
7071 processSync(mapper);
7072 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007073 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
7074
7075 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7076 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7077}
7078
Michael Wrightd02c5b62014-02-10 15:10:22 -08007079// --- MultiTouchInputMapperTest ---
7080
7081class MultiTouchInputMapperTest : public TouchInputMapperTest {
7082protected:
7083 void prepareAxes(int axes);
7084
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007085 void processPosition(MultiTouchInputMapper& mapper, int32_t x, int32_t y);
7086 void processTouchMajor(MultiTouchInputMapper& mapper, int32_t touchMajor);
7087 void processTouchMinor(MultiTouchInputMapper& mapper, int32_t touchMinor);
7088 void processToolMajor(MultiTouchInputMapper& mapper, int32_t toolMajor);
7089 void processToolMinor(MultiTouchInputMapper& mapper, int32_t toolMinor);
7090 void processOrientation(MultiTouchInputMapper& mapper, int32_t orientation);
7091 void processPressure(MultiTouchInputMapper& mapper, int32_t pressure);
7092 void processDistance(MultiTouchInputMapper& mapper, int32_t distance);
7093 void processId(MultiTouchInputMapper& mapper, int32_t id);
7094 void processSlot(MultiTouchInputMapper& mapper, int32_t slot);
7095 void processToolType(MultiTouchInputMapper& mapper, int32_t toolType);
7096 void processKey(MultiTouchInputMapper& mapper, int32_t code, int32_t value);
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00007097 void processHidUsage(MultiTouchInputMapper& mapper, int32_t usageCode, int32_t value);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007098 void processMTSync(MultiTouchInputMapper& mapper);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00007099 void processSync(MultiTouchInputMapper& mapper, nsecs_t eventTime = ARBITRARY_TIME,
7100 nsecs_t readTime = READ_TIME);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007101};
7102
7103void MultiTouchInputMapperTest::prepareAxes(int axes) {
7104 if (axes & POSITION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007105 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
7106 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007107 }
7108 if (axes & TOUCH) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007109 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN,
7110 RAW_TOUCH_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007111 if (axes & MINOR) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007112 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN,
7113 RAW_TOUCH_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007114 }
7115 }
7116 if (axes & TOOL) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007117 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7118 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007119 if (axes & MINOR) {
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007120 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MIN,
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007121 RAW_TOOL_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007122 }
7123 }
7124 if (axes & ORIENTATION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007125 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_ORIENTATION, RAW_ORIENTATION_MIN,
7126 RAW_ORIENTATION_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007127 }
7128 if (axes & PRESSURE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007129 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_PRESSURE, RAW_PRESSURE_MIN,
7130 RAW_PRESSURE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007131 }
7132 if (axes & DISTANCE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007133 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_DISTANCE, RAW_DISTANCE_MIN,
7134 RAW_DISTANCE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007135 }
7136 if (axes & ID) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007137 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TRACKING_ID, RAW_ID_MIN, RAW_ID_MAX, 0,
7138 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007139 }
7140 if (axes & SLOT) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007141 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_SLOT, RAW_SLOT_MIN, RAW_SLOT_MAX, 0, 0);
7142 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007143 }
7144 if (axes & TOOL_TYPE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007145 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007146 }
7147}
7148
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007149void MultiTouchInputMapperTest::processPosition(MultiTouchInputMapper& mapper, int32_t x,
7150 int32_t y) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007151 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
7152 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007153}
7154
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007155void MultiTouchInputMapperTest::processTouchMajor(MultiTouchInputMapper& mapper,
7156 int32_t touchMajor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007157 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOUCH_MAJOR, touchMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007158}
7159
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007160void MultiTouchInputMapperTest::processTouchMinor(MultiTouchInputMapper& mapper,
7161 int32_t touchMinor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007162 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOUCH_MINOR, touchMinor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007163}
7164
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007165void MultiTouchInputMapperTest::processToolMajor(MultiTouchInputMapper& mapper, int32_t toolMajor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007166 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_WIDTH_MAJOR, toolMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007167}
7168
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007169void MultiTouchInputMapperTest::processToolMinor(MultiTouchInputMapper& mapper, int32_t toolMinor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007170 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_WIDTH_MINOR, toolMinor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007171}
7172
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007173void MultiTouchInputMapperTest::processOrientation(MultiTouchInputMapper& mapper,
7174 int32_t orientation) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007175 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_ORIENTATION, orientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007176}
7177
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007178void MultiTouchInputMapperTest::processPressure(MultiTouchInputMapper& mapper, int32_t pressure) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007179 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_PRESSURE, pressure);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007180}
7181
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007182void MultiTouchInputMapperTest::processDistance(MultiTouchInputMapper& mapper, int32_t distance) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007183 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_DISTANCE, distance);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007184}
7185
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007186void MultiTouchInputMapperTest::processId(MultiTouchInputMapper& mapper, int32_t id) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007187 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TRACKING_ID, id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007188}
7189
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007190void MultiTouchInputMapperTest::processSlot(MultiTouchInputMapper& mapper, int32_t slot) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007191 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_SLOT, slot);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007192}
7193
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007194void MultiTouchInputMapperTest::processToolType(MultiTouchInputMapper& mapper, int32_t toolType) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007195 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOOL_TYPE, toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007196}
7197
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007198void MultiTouchInputMapperTest::processKey(MultiTouchInputMapper& mapper, int32_t code,
7199 int32_t value) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007200 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007201}
7202
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00007203void MultiTouchInputMapperTest::processHidUsage(MultiTouchInputMapper& mapper, int32_t usageCode,
7204 int32_t value) {
7205 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, usageCode);
7206 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, value);
7207}
7208
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007209void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper& mapper) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007210 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_MT_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007211}
7212
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00007213void MultiTouchInputMapperTest::processSync(MultiTouchInputMapper& mapper, nsecs_t eventTime,
7214 nsecs_t readTime) {
7215 process(mapper, eventTime, readTime, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007216}
7217
Michael Wrightd02c5b62014-02-10 15:10:22 -08007218TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackingIds) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007219 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007220 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007221 prepareAxes(POSITION);
7222 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007223 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007224
arthurhungdcef2dc2020-08-11 14:47:50 +08007225 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007226
7227 NotifyMotionArgs motionArgs;
7228
7229 // Two fingers down at once.
7230 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7231 processPosition(mapper, x1, y1);
7232 processMTSync(mapper);
7233 processPosition(mapper, x2, y2);
7234 processMTSync(mapper);
7235 processSync(mapper);
7236
7237 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7238 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7239 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7240 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7241 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7242 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
7243 ASSERT_EQ(0, motionArgs.flags);
7244 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7245 ASSERT_EQ(0, motionArgs.buttonState);
7246 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007247 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007248 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007249 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007250 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7251 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7252 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7253 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7254 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7255
7256 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7257 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7258 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7259 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7260 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007261 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007262 ASSERT_EQ(0, motionArgs.flags);
7263 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7264 ASSERT_EQ(0, motionArgs.buttonState);
7265 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007266 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007267 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007268 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007269 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007270 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007271 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7272 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7273 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7274 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7275 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7276 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7277 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7278
7279 // Move.
7280 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7281 processPosition(mapper, x1, y1);
7282 processMTSync(mapper);
7283 processPosition(mapper, x2, y2);
7284 processMTSync(mapper);
7285 processSync(mapper);
7286
7287 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7288 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7289 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7290 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7291 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7292 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7293 ASSERT_EQ(0, motionArgs.flags);
7294 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7295 ASSERT_EQ(0, motionArgs.buttonState);
7296 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007297 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007298 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007299 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007300 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007301 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007302 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7303 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7304 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7305 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7306 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7307 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7308 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7309
7310 // First finger up.
7311 x2 += 15; y2 -= 20;
7312 processPosition(mapper, x2, y2);
7313 processMTSync(mapper);
7314 processSync(mapper);
7315
7316 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7317 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7318 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7319 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7320 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007321 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007322 ASSERT_EQ(0, motionArgs.flags);
7323 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7324 ASSERT_EQ(0, motionArgs.buttonState);
7325 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007326 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007327 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007328 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007329 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007330 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007331 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7332 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7333 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7334 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7335 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7336 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7337 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7338
7339 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7340 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7341 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7342 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7343 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7344 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7345 ASSERT_EQ(0, motionArgs.flags);
7346 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7347 ASSERT_EQ(0, motionArgs.buttonState);
7348 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007349 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007350 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007351 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007352 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7353 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7354 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7355 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7356 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7357
7358 // Move.
7359 x2 += 20; y2 -= 25;
7360 processPosition(mapper, x2, y2);
7361 processMTSync(mapper);
7362 processSync(mapper);
7363
7364 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7365 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7366 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7367 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7368 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7369 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7370 ASSERT_EQ(0, motionArgs.flags);
7371 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7372 ASSERT_EQ(0, motionArgs.buttonState);
7373 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007374 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007375 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007376 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007377 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7378 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7379 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7380 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7381 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7382
7383 // New finger down.
7384 int32_t x3 = 700, y3 = 300;
7385 processPosition(mapper, x2, y2);
7386 processMTSync(mapper);
7387 processPosition(mapper, x3, y3);
7388 processMTSync(mapper);
7389 processSync(mapper);
7390
7391 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7392 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7393 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7394 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7395 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007396 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007397 ASSERT_EQ(0, motionArgs.flags);
7398 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7399 ASSERT_EQ(0, motionArgs.buttonState);
7400 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007401 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007402 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007403 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007404 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007405 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007406 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7407 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7408 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7409 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7410 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7411 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7412 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7413
7414 // Second finger up.
7415 x3 += 30; y3 -= 20;
7416 processPosition(mapper, x3, y3);
7417 processMTSync(mapper);
7418 processSync(mapper);
7419
7420 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7421 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7422 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7423 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7424 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007425 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007426 ASSERT_EQ(0, motionArgs.flags);
7427 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7428 ASSERT_EQ(0, motionArgs.buttonState);
7429 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007430 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007431 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007432 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007433 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007434 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007435 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7436 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7437 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7438 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7439 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7440 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7441 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7442
7443 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7444 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7445 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7446 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7447 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7448 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7449 ASSERT_EQ(0, motionArgs.flags);
7450 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7451 ASSERT_EQ(0, motionArgs.buttonState);
7452 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007453 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007454 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007455 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007456 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7457 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7458 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7459 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7460 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7461
7462 // Last finger up.
7463 processMTSync(mapper);
7464 processSync(mapper);
7465
7466 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7467 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7468 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7469 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7470 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7471 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
7472 ASSERT_EQ(0, motionArgs.flags);
7473 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7474 ASSERT_EQ(0, motionArgs.buttonState);
7475 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007476 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007477 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007478 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007479 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7480 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7481 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7482 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7483 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7484
7485 // Should not have sent any more keys or motions.
7486 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7487 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7488}
7489
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007490TEST_F(MultiTouchInputMapperTest, AxisResolution_IsPopulated) {
7491 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007492 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007493
7494 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, /*flat*/ 0,
7495 /*fuzz*/ 0, /*resolution*/ 10);
7496 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, /*flat*/ 0,
7497 /*fuzz*/ 0, /*resolution*/ 11);
7498 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX,
7499 /*flat*/ 0, /*fuzz*/ 0, /*resolution*/ 12);
7500 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX,
7501 /*flat*/ 0, /*fuzz*/ 0, /*resolution*/ 13);
7502 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7503 /*flat*/ 0, /*flat*/ 0, /*resolution*/ 14);
7504 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7505 /*flat*/ 0, /*flat*/ 0, /*resolution*/ 15);
7506
Arpit Singha8c236b2023-04-25 13:56:05 +00007507 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007508
7509 // X and Y axes
7510 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_X, 10 / X_PRECISION);
7511 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_Y, 11 / Y_PRECISION);
7512 // Touch major and minor
7513 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOUCH_MAJOR, 12 * GEOMETRIC_SCALE);
7514 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOUCH_MINOR, 13 * GEOMETRIC_SCALE);
7515 // Tool major and minor
7516 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOOL_MAJOR, 14 * GEOMETRIC_SCALE);
7517 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOOL_MINOR, 15 * GEOMETRIC_SCALE);
7518}
7519
7520TEST_F(MultiTouchInputMapperTest, TouchMajorAndMinorAxes_DoNotAppearIfNotSupported) {
7521 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007522 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007523
7524 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, /*flat*/ 0,
7525 /*fuzz*/ 0, /*resolution*/ 10);
7526 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, /*flat*/ 0,
7527 /*fuzz*/ 0, /*resolution*/ 11);
7528
7529 // We do not add ABS_MT_TOUCH_MAJOR / MINOR or ABS_MT_WIDTH_MAJOR / MINOR axes
7530
Arpit Singha8c236b2023-04-25 13:56:05 +00007531 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007532
7533 // Touch major and minor
7534 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOUCH_MAJOR);
7535 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOUCH_MINOR);
7536 // Tool major and minor
7537 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOOL_MAJOR);
7538 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOOL_MINOR);
7539}
7540
Michael Wrightd02c5b62014-02-10 15:10:22 -08007541TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingIds) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007542 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007543 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007544 prepareAxes(POSITION | ID);
7545 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007546 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007547
arthurhungdcef2dc2020-08-11 14:47:50 +08007548 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007549
7550 NotifyMotionArgs motionArgs;
7551
7552 // Two fingers down at once.
7553 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7554 processPosition(mapper, x1, y1);
7555 processId(mapper, 1);
7556 processMTSync(mapper);
7557 processPosition(mapper, x2, y2);
7558 processId(mapper, 2);
7559 processMTSync(mapper);
7560 processSync(mapper);
7561
7562 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7563 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007564 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007565 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007566 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007567 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7568 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7569
7570 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007571 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007572 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007573 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007574 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007575 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007576 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007577 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7578 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7579 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7580 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7581
7582 // Move.
7583 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7584 processPosition(mapper, x1, y1);
7585 processId(mapper, 1);
7586 processMTSync(mapper);
7587 processPosition(mapper, x2, y2);
7588 processId(mapper, 2);
7589 processMTSync(mapper);
7590 processSync(mapper);
7591
7592 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7593 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007594 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007595 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007596 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007597 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007598 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007599 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7600 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7601 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7602 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7603
7604 // First finger up.
7605 x2 += 15; y2 -= 20;
7606 processPosition(mapper, x2, y2);
7607 processId(mapper, 2);
7608 processMTSync(mapper);
7609 processSync(mapper);
7610
7611 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007612 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007613 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007614 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007615 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007616 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007617 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007618 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7619 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7620 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7621 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7622
7623 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7624 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007625 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007626 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007627 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007628 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7629 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7630
7631 // Move.
7632 x2 += 20; y2 -= 25;
7633 processPosition(mapper, x2, y2);
7634 processId(mapper, 2);
7635 processMTSync(mapper);
7636 processSync(mapper);
7637
7638 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7639 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007640 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007641 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007642 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007643 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7644 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7645
7646 // New finger down.
7647 int32_t x3 = 700, y3 = 300;
7648 processPosition(mapper, x2, y2);
7649 processId(mapper, 2);
7650 processMTSync(mapper);
7651 processPosition(mapper, x3, y3);
7652 processId(mapper, 3);
7653 processMTSync(mapper);
7654 processSync(mapper);
7655
7656 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007657 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007658 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007659 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007660 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007661 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007662 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007663 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7664 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7665 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7666 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7667
7668 // Second finger up.
7669 x3 += 30; y3 -= 20;
7670 processPosition(mapper, x3, y3);
7671 processId(mapper, 3);
7672 processMTSync(mapper);
7673 processSync(mapper);
7674
7675 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007676 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007677 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007678 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007679 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007680 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007681 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007682 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7683 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7684 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7685 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7686
7687 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7688 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007689 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007690 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007691 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007692 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7693 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7694
7695 // Last finger up.
7696 processMTSync(mapper);
7697 processSync(mapper);
7698
7699 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7700 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007701 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007702 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007703 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007704 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7705 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7706
7707 // Should not have sent any more keys or motions.
7708 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7709 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7710}
7711
7712TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithSlots) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007713 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007714 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007715 prepareAxes(POSITION | ID | SLOT);
7716 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007717 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007718
arthurhungdcef2dc2020-08-11 14:47:50 +08007719 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007720
7721 NotifyMotionArgs motionArgs;
7722
7723 // Two fingers down at once.
7724 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7725 processPosition(mapper, x1, y1);
7726 processId(mapper, 1);
7727 processSlot(mapper, 1);
7728 processPosition(mapper, x2, y2);
7729 processId(mapper, 2);
7730 processSync(mapper);
7731
7732 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7733 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007734 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007735 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007736 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007737 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7738 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7739
7740 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007741 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007742 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007743 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007744 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007745 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007746 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007747 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7748 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7749 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7750 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7751
7752 // Move.
7753 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7754 processSlot(mapper, 0);
7755 processPosition(mapper, x1, y1);
7756 processSlot(mapper, 1);
7757 processPosition(mapper, x2, y2);
7758 processSync(mapper);
7759
7760 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7761 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007762 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007763 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007764 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007765 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007766 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007767 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7768 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7769 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7770 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7771
7772 // First finger up.
7773 x2 += 15; y2 -= 20;
7774 processSlot(mapper, 0);
7775 processId(mapper, -1);
7776 processSlot(mapper, 1);
7777 processPosition(mapper, x2, y2);
7778 processSync(mapper);
7779
7780 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007781 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007782 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007783 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007784 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007785 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007786 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007787 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7788 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7789 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7790 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7791
7792 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7793 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007794 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007795 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007796 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007797 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7798 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7799
7800 // Move.
7801 x2 += 20; y2 -= 25;
7802 processPosition(mapper, x2, y2);
7803 processSync(mapper);
7804
7805 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7806 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007807 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007808 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007809 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007810 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7811 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7812
7813 // New finger down.
7814 int32_t x3 = 700, y3 = 300;
7815 processPosition(mapper, x2, y2);
7816 processSlot(mapper, 0);
7817 processId(mapper, 3);
7818 processPosition(mapper, x3, y3);
7819 processSync(mapper);
7820
7821 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007822 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007823 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007824 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007825 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007826 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007827 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007828 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7829 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7830 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7831 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7832
7833 // Second finger up.
7834 x3 += 30; y3 -= 20;
7835 processSlot(mapper, 1);
7836 processId(mapper, -1);
7837 processSlot(mapper, 0);
7838 processPosition(mapper, x3, y3);
7839 processSync(mapper);
7840
7841 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007842 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007843 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007844 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007845 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007846 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007847 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007848 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7849 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7850 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7851 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7852
7853 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7854 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007855 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007856 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007857 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007858 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7859 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7860
7861 // Last finger up.
7862 processId(mapper, -1);
7863 processSync(mapper);
7864
7865 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7866 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007867 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007868 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007869 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007870 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7871 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7872
7873 // Should not have sent any more keys or motions.
7874 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7875 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7876}
7877
7878TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007879 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007880 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007881 prepareAxes(POSITION | TOUCH | TOOL | PRESSURE | ORIENTATION | ID | MINOR | DISTANCE);
Arpit Singha8c236b2023-04-25 13:56:05 +00007882 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007883
7884 // These calculations are based on the input device calibration documentation.
7885 int32_t rawX = 100;
7886 int32_t rawY = 200;
7887 int32_t rawTouchMajor = 7;
7888 int32_t rawTouchMinor = 6;
7889 int32_t rawToolMajor = 9;
7890 int32_t rawToolMinor = 8;
7891 int32_t rawPressure = 11;
7892 int32_t rawDistance = 0;
7893 int32_t rawOrientation = 3;
7894 int32_t id = 5;
7895
7896 float x = toDisplayX(rawX);
7897 float y = toDisplayY(rawY);
7898 float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
7899 float size = avg(rawTouchMajor, rawTouchMinor) / RAW_TOUCH_MAX;
7900 float toolMajor = float(rawToolMajor) * GEOMETRIC_SCALE;
7901 float toolMinor = float(rawToolMinor) * GEOMETRIC_SCALE;
7902 float touchMajor = float(rawTouchMajor) * GEOMETRIC_SCALE;
7903 float touchMinor = float(rawTouchMinor) * GEOMETRIC_SCALE;
7904 float orientation = float(rawOrientation) / RAW_ORIENTATION_MAX * M_PI_2;
7905 float distance = float(rawDistance);
7906
7907 processPosition(mapper, rawX, rawY);
7908 processTouchMajor(mapper, rawTouchMajor);
7909 processTouchMinor(mapper, rawTouchMinor);
7910 processToolMajor(mapper, rawToolMajor);
7911 processToolMinor(mapper, rawToolMinor);
7912 processPressure(mapper, rawPressure);
7913 processOrientation(mapper, rawOrientation);
7914 processDistance(mapper, rawDistance);
7915 processId(mapper, id);
7916 processMTSync(mapper);
7917 processSync(mapper);
7918
7919 NotifyMotionArgs args;
7920 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7921 ASSERT_EQ(0, args.pointerProperties[0].id);
7922 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7923 x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor,
7924 orientation, distance));
Prabir Pradhan9a53b552024-06-04 02:59:40 +00007925 ASSERT_EQ(args.flags, AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007926}
7927
7928TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_GeometricCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007929 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007930 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007931 prepareAxes(POSITION | TOUCH | TOOL | MINOR);
7932 addConfigurationProperty("touch.size.calibration", "geometric");
Arpit Singha8c236b2023-04-25 13:56:05 +00007933 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007934
7935 // These calculations are based on the input device calibration documentation.
7936 int32_t rawX = 100;
7937 int32_t rawY = 200;
7938 int32_t rawTouchMajor = 140;
7939 int32_t rawTouchMinor = 120;
7940 int32_t rawToolMajor = 180;
7941 int32_t rawToolMinor = 160;
7942
7943 float x = toDisplayX(rawX);
7944 float y = toDisplayY(rawY);
7945 float size = avg(rawTouchMajor, rawTouchMinor) / RAW_TOUCH_MAX;
7946 float toolMajor = float(rawToolMajor) * GEOMETRIC_SCALE;
7947 float toolMinor = float(rawToolMinor) * GEOMETRIC_SCALE;
7948 float touchMajor = float(rawTouchMajor) * GEOMETRIC_SCALE;
7949 float touchMinor = float(rawTouchMinor) * GEOMETRIC_SCALE;
7950
7951 processPosition(mapper, rawX, rawY);
7952 processTouchMajor(mapper, rawTouchMajor);
7953 processTouchMinor(mapper, rawTouchMinor);
7954 processToolMajor(mapper, rawToolMajor);
7955 processToolMinor(mapper, rawToolMinor);
7956 processMTSync(mapper);
7957 processSync(mapper);
7958
7959 NotifyMotionArgs args;
7960 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7961 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7962 x, y, 1.0f, size, touchMajor, touchMinor, toolMajor, toolMinor, 0, 0));
7963}
7964
7965TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_SummedLinearCalibration) {
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);
7969 addConfigurationProperty("touch.size.calibration", "diameter");
7970 addConfigurationProperty("touch.size.scale", "10");
7971 addConfigurationProperty("touch.size.bias", "160");
7972 addConfigurationProperty("touch.size.isSummed", "1");
Arpit Singha8c236b2023-04-25 13:56:05 +00007973 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007974
7975 // These calculations are based on the input device calibration documentation.
7976 // Note: We only provide a single common touch/tool value because the device is assumed
7977 // not to emit separate values for each pointer (isSummed = 1).
7978 int32_t rawX = 100;
7979 int32_t rawY = 200;
7980 int32_t rawX2 = 150;
7981 int32_t rawY2 = 250;
7982 int32_t rawTouchMajor = 5;
7983 int32_t rawToolMajor = 8;
7984
7985 float x = toDisplayX(rawX);
7986 float y = toDisplayY(rawY);
7987 float x2 = toDisplayX(rawX2);
7988 float y2 = toDisplayY(rawY2);
7989 float size = float(rawTouchMajor) / 2 / RAW_TOUCH_MAX;
7990 float touch = float(rawTouchMajor) / 2 * 10.0f + 160.0f;
7991 float tool = float(rawToolMajor) / 2 * 10.0f + 160.0f;
7992
7993 processPosition(mapper, rawX, rawY);
7994 processTouchMajor(mapper, rawTouchMajor);
7995 processToolMajor(mapper, rawToolMajor);
7996 processMTSync(mapper);
7997 processPosition(mapper, rawX2, rawY2);
7998 processTouchMajor(mapper, rawTouchMajor);
7999 processToolMajor(mapper, rawToolMajor);
8000 processMTSync(mapper);
8001 processSync(mapper);
8002
8003 NotifyMotionArgs args;
8004 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8005 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
8006
8007 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08008008 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07008009 ASSERT_EQ(size_t(2), args.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08008010 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8011 x, y, 1.0f, size, touch, touch, tool, tool, 0, 0));
8012 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[1],
8013 x2, y2, 1.0f, size, touch, touch, tool, tool, 0, 0));
8014}
8015
8016TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_AreaCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008017 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008018 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008019 prepareAxes(POSITION | TOUCH | TOOL);
8020 addConfigurationProperty("touch.size.calibration", "area");
8021 addConfigurationProperty("touch.size.scale", "43");
8022 addConfigurationProperty("touch.size.bias", "3");
Arpit Singha8c236b2023-04-25 13:56:05 +00008023 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008024
8025 // These calculations are based on the input device calibration documentation.
8026 int32_t rawX = 100;
8027 int32_t rawY = 200;
8028 int32_t rawTouchMajor = 5;
8029 int32_t rawToolMajor = 8;
8030
8031 float x = toDisplayX(rawX);
8032 float y = toDisplayY(rawY);
8033 float size = float(rawTouchMajor) / RAW_TOUCH_MAX;
8034 float touch = sqrtf(rawTouchMajor) * 43.0f + 3.0f;
8035 float tool = sqrtf(rawToolMajor) * 43.0f + 3.0f;
8036
8037 processPosition(mapper, rawX, rawY);
8038 processTouchMajor(mapper, rawTouchMajor);
8039 processToolMajor(mapper, rawToolMajor);
8040 processMTSync(mapper);
8041 processSync(mapper);
8042
8043 NotifyMotionArgs args;
8044 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8045 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8046 x, y, 1.0f, size, touch, touch, tool, tool, 0, 0));
8047}
8048
8049TEST_F(MultiTouchInputMapperTest, Process_PressureAxis_AmplitudeCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008050 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008051 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008052 prepareAxes(POSITION | PRESSURE);
8053 addConfigurationProperty("touch.pressure.calibration", "amplitude");
8054 addConfigurationProperty("touch.pressure.scale", "0.01");
Arpit Singha8c236b2023-04-25 13:56:05 +00008055 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008056
Michael Wrightaa449c92017-12-13 21:21:43 +00008057 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +00008058 mapper.populateDeviceInfo(info);
Michael Wrightaa449c92017-12-13 21:21:43 +00008059 ASSERT_NO_FATAL_FAILURE(assertMotionRange(info,
8060 AINPUT_MOTION_RANGE_PRESSURE, AINPUT_SOURCE_TOUCHSCREEN,
8061 0.0f, RAW_PRESSURE_MAX * 0.01, 0.0f, 0.0f));
8062
Michael Wrightd02c5b62014-02-10 15:10:22 -08008063 // These calculations are based on the input device calibration documentation.
8064 int32_t rawX = 100;
8065 int32_t rawY = 200;
8066 int32_t rawPressure = 60;
8067
8068 float x = toDisplayX(rawX);
8069 float y = toDisplayY(rawY);
8070 float pressure = float(rawPressure) * 0.01f;
8071
8072 processPosition(mapper, rawX, rawY);
8073 processPressure(mapper, rawPressure);
8074 processMTSync(mapper);
8075 processSync(mapper);
8076
8077 NotifyMotionArgs args;
8078 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8079 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8080 x, y, pressure, 0, 0, 0, 0, 0, 0, 0));
8081}
8082
8083TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllButtons) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008084 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008085 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008086 prepareAxes(POSITION | ID | SLOT);
Arpit Singha8c236b2023-04-25 13:56:05 +00008087 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008088
8089 NotifyMotionArgs motionArgs;
8090 NotifyKeyArgs keyArgs;
8091
8092 processId(mapper, 1);
8093 processPosition(mapper, 100, 200);
8094 processSync(mapper);
8095 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8096 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8097 ASSERT_EQ(0, motionArgs.buttonState);
8098
8099 // press BTN_LEFT, release BTN_LEFT
8100 processKey(mapper, BTN_LEFT, 1);
8101 processSync(mapper);
8102 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8103 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
8104 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
8105
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008106 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8107 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8108 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
8109
Michael Wrightd02c5b62014-02-10 15:10:22 -08008110 processKey(mapper, BTN_LEFT, 0);
8111 processSync(mapper);
8112 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008113 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008114 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008115
8116 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008117 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008118 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008119
8120 // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
8121 processKey(mapper, BTN_RIGHT, 1);
8122 processKey(mapper, BTN_MIDDLE, 1);
8123 processSync(mapper);
8124 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8125 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
8126 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
8127 motionArgs.buttonState);
8128
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008129 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8130 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8131 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
8132
8133 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8134 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8135 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
8136 motionArgs.buttonState);
8137
Michael Wrightd02c5b62014-02-10 15:10:22 -08008138 processKey(mapper, BTN_RIGHT, 0);
8139 processSync(mapper);
8140 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008141 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008142 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008143
8144 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008145 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008146 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008147
8148 processKey(mapper, BTN_MIDDLE, 0);
8149 processSync(mapper);
8150 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008151 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008152 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008153
8154 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008155 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008156 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008157
8158 // press BTN_BACK, release BTN_BACK
8159 processKey(mapper, BTN_BACK, 1);
8160 processSync(mapper);
8161 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8162 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8163 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008164
Michael Wrightd02c5b62014-02-10 15:10:22 -08008165 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008166 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008167 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
8168
8169 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8170 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8171 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008172
8173 processKey(mapper, BTN_BACK, 0);
8174 processSync(mapper);
8175 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008176 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008177 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008178
8179 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008180 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008181 ASSERT_EQ(0, motionArgs.buttonState);
8182
Michael Wrightd02c5b62014-02-10 15:10:22 -08008183 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8184 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8185 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
8186
8187 // press BTN_SIDE, release BTN_SIDE
8188 processKey(mapper, BTN_SIDE, 1);
8189 processSync(mapper);
8190 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8191 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8192 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008193
Michael Wrightd02c5b62014-02-10 15:10:22 -08008194 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008195 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008196 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
8197
8198 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8199 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8200 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008201
8202 processKey(mapper, BTN_SIDE, 0);
8203 processSync(mapper);
8204 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008205 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008206 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008207
8208 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008209 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008210 ASSERT_EQ(0, motionArgs.buttonState);
8211
Michael Wrightd02c5b62014-02-10 15:10:22 -08008212 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8213 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8214 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
8215
8216 // press BTN_FORWARD, release BTN_FORWARD
8217 processKey(mapper, BTN_FORWARD, 1);
8218 processSync(mapper);
8219 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8220 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8221 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008222
Michael Wrightd02c5b62014-02-10 15:10:22 -08008223 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008224 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008225 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
8226
8227 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8228 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8229 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008230
8231 processKey(mapper, BTN_FORWARD, 0);
8232 processSync(mapper);
8233 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008234 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008235 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008236
8237 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008238 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008239 ASSERT_EQ(0, motionArgs.buttonState);
8240
Michael Wrightd02c5b62014-02-10 15:10:22 -08008241 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8242 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8243 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
8244
8245 // press BTN_EXTRA, release BTN_EXTRA
8246 processKey(mapper, BTN_EXTRA, 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_FORWARD, 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_FORWARD, 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_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008259
8260 processKey(mapper, BTN_EXTRA, 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_FORWARD, keyArgs.keyCode);
8273
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008274 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
8275
Michael Wrightd02c5b62014-02-10 15:10:22 -08008276 // press BTN_STYLUS, release BTN_STYLUS
8277 processKey(mapper, BTN_STYLUS, 1);
8278 processSync(mapper);
8279 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8280 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008281 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
8282
8283 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8284 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8285 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008286
8287 processKey(mapper, BTN_STYLUS, 0);
8288 processSync(mapper);
8289 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008290 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008291 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008292
8293 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008294 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008295 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008296
8297 // press BTN_STYLUS2, release BTN_STYLUS2
8298 processKey(mapper, BTN_STYLUS2, 1);
8299 processSync(mapper);
8300 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8301 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008302 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
8303
8304 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8305 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8306 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008307
8308 processKey(mapper, BTN_STYLUS2, 0);
8309 processSync(mapper);
8310 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008311 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008312 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008313
8314 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008315 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008316 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008317
8318 // release touch
8319 processId(mapper, -1);
8320 processSync(mapper);
8321 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8322 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8323 ASSERT_EQ(0, motionArgs.buttonState);
8324}
8325
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008326TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleMappedStylusButtons) {
8327 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008328 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008329 prepareAxes(POSITION | ID | SLOT);
Arpit Singha8c236b2023-04-25 13:56:05 +00008330 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008331
8332 mFakeEventHub->addKey(EVENTHUB_ID, BTN_A, 0, AKEYCODE_STYLUS_BUTTON_PRIMARY, 0);
8333 mFakeEventHub->addKey(EVENTHUB_ID, 0, 0xabcd, AKEYCODE_STYLUS_BUTTON_SECONDARY, 0);
8334
8335 // Touch down.
8336 processId(mapper, 1);
8337 processPosition(mapper, 100, 200);
8338 processSync(mapper);
8339 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8340 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithButtonState(0))));
8341
8342 // Press and release button mapped to the primary stylus button.
8343 processKey(mapper, BTN_A, 1);
8344 processSync(mapper);
8345 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8346 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
8347 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
8348 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8349 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
8350 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
8351
8352 processKey(mapper, BTN_A, 0);
8353 processSync(mapper);
8354 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8355 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithButtonState(0))));
8356 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8357 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
8358
8359 // Press and release the HID usage mapped to the secondary stylus button.
8360 processHidUsage(mapper, 0xabcd, 1);
8361 processSync(mapper);
8362 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8363 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
8364 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY))));
8365 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8366 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
8367 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY))));
8368
8369 processHidUsage(mapper, 0xabcd, 0);
8370 processSync(mapper);
8371 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8372 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithButtonState(0))));
8373 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8374 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
8375
8376 // Release touch.
8377 processId(mapper, -1);
8378 processSync(mapper);
8379 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8380 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
8381}
8382
Michael Wrightd02c5b62014-02-10 15:10:22 -08008383TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008384 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008385 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008386 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00008387 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008388
8389 NotifyMotionArgs motionArgs;
8390
8391 // default tool type is finger
8392 processId(mapper, 1);
8393 processPosition(mapper, 100, 200);
8394 processSync(mapper);
8395 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8396 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008397 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008398
8399 // eraser
8400 processKey(mapper, BTN_TOOL_RUBBER, 1);
8401 processSync(mapper);
8402 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8403 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008404 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008405
8406 // stylus
8407 processKey(mapper, BTN_TOOL_RUBBER, 0);
8408 processKey(mapper, BTN_TOOL_PEN, 1);
8409 processSync(mapper);
8410 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8411 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008412 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008413
8414 // brush
8415 processKey(mapper, BTN_TOOL_PEN, 0);
8416 processKey(mapper, BTN_TOOL_BRUSH, 1);
8417 processSync(mapper);
8418 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8419 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008420 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008421
8422 // pencil
8423 processKey(mapper, BTN_TOOL_BRUSH, 0);
8424 processKey(mapper, BTN_TOOL_PENCIL, 1);
8425 processSync(mapper);
8426 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8427 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008428 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008429
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08008430 // air-brush
Michael Wrightd02c5b62014-02-10 15:10:22 -08008431 processKey(mapper, BTN_TOOL_PENCIL, 0);
8432 processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
8433 processSync(mapper);
8434 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8435 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008436 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008437
8438 // mouse
8439 processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
8440 processKey(mapper, BTN_TOOL_MOUSE, 1);
8441 processSync(mapper);
8442 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8443 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008444 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008445
8446 // lens
8447 processKey(mapper, BTN_TOOL_MOUSE, 0);
8448 processKey(mapper, BTN_TOOL_LENS, 1);
8449 processSync(mapper);
8450 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8451 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008452 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008453
8454 // double-tap
8455 processKey(mapper, BTN_TOOL_LENS, 0);
8456 processKey(mapper, BTN_TOOL_DOUBLETAP, 1);
8457 processSync(mapper);
8458 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8459 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008460 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008461
8462 // triple-tap
8463 processKey(mapper, BTN_TOOL_DOUBLETAP, 0);
8464 processKey(mapper, BTN_TOOL_TRIPLETAP, 1);
8465 processSync(mapper);
8466 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8467 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008468 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008469
8470 // quad-tap
8471 processKey(mapper, BTN_TOOL_TRIPLETAP, 0);
8472 processKey(mapper, BTN_TOOL_QUADTAP, 1);
8473 processSync(mapper);
8474 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8475 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008476 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008477
8478 // finger
8479 processKey(mapper, BTN_TOOL_QUADTAP, 0);
8480 processKey(mapper, BTN_TOOL_FINGER, 1);
8481 processSync(mapper);
8482 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8483 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, 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 // stylus trumps finger
8487 processKey(mapper, BTN_TOOL_PEN, 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::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008492
8493 // eraser trumps stylus
8494 processKey(mapper, BTN_TOOL_RUBBER, 1);
8495 processSync(mapper);
8496 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8497 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008498 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008499
8500 // mouse trumps eraser
8501 processKey(mapper, BTN_TOOL_MOUSE, 1);
8502 processSync(mapper);
8503 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8504 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008505 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008506
8507 // MT tool type trumps BTN tool types: MT_TOOL_FINGER
8508 processToolType(mapper, MT_TOOL_FINGER); // this is the first time we send MT_TOOL_TYPE
8509 processSync(mapper);
8510 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8511 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008512 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008513
8514 // MT tool type trumps BTN tool types: MT_TOOL_PEN
8515 processToolType(mapper, MT_TOOL_PEN);
8516 processSync(mapper);
8517 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8518 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008519 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008520
8521 // back to default tool type
8522 processToolType(mapper, -1); // use a deliberately undefined tool type, for testing
8523 processKey(mapper, BTN_TOOL_MOUSE, 0);
8524 processKey(mapper, BTN_TOOL_RUBBER, 0);
8525 processKey(mapper, BTN_TOOL_PEN, 0);
8526 processKey(mapper, BTN_TOOL_FINGER, 0);
8527 processSync(mapper);
8528 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8529 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008530 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008531}
8532
8533TEST_F(MultiTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008534 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008535 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008536 prepareAxes(POSITION | ID | SLOT);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008537 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00008538 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008539
8540 NotifyMotionArgs motionArgs;
8541
8542 // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0
8543 processId(mapper, 1);
8544 processPosition(mapper, 100, 200);
8545 processSync(mapper);
8546 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8547 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8548 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8549 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8550
8551 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8552 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8553 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8554 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8555
8556 // move a little
8557 processPosition(mapper, 150, 250);
8558 processSync(mapper);
8559 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8560 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8561 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8562 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8563
8564 // down when BTN_TOUCH is pressed, pressure defaults to 1
8565 processKey(mapper, BTN_TOUCH, 1);
8566 processSync(mapper);
8567 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8568 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8569 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8570 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8571
8572 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8573 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8574 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8575 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8576
8577 // up when BTN_TOUCH is released, hover restored
8578 processKey(mapper, BTN_TOUCH, 0);
8579 processSync(mapper);
8580 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8581 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8582 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8583 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8584
8585 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8586 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8587 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8588 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8589
8590 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8591 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8592 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8593 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8594
8595 // exit hover when pointer goes away
8596 processId(mapper, -1);
8597 processSync(mapper);
8598 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8599 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8600 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8601 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8602}
8603
8604TEST_F(MultiTouchInputMapperTest, Process_WhenAbsMTPressureIsPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008605 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008606 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008607 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00008608 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008609
8610 NotifyMotionArgs motionArgs;
8611
8612 // initially hovering because pressure is 0
8613 processId(mapper, 1);
8614 processPosition(mapper, 100, 200);
8615 processPressure(mapper, 0);
8616 processSync(mapper);
8617 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8618 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8619 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8620 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8621
8622 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8623 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8624 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8625 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8626
8627 // move a little
8628 processPosition(mapper, 150, 250);
8629 processSync(mapper);
8630 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8631 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8632 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8633 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8634
8635 // down when pressure becomes non-zero
8636 processPressure(mapper, RAW_PRESSURE_MAX);
8637 processSync(mapper);
8638 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8639 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8640 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8641 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8642
8643 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8644 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8645 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8646 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8647
8648 // up when pressure becomes 0, hover restored
8649 processPressure(mapper, 0);
8650 processSync(mapper);
8651 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8652 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8653 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8654 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8655
8656 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8657 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8658 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8659 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8660
8661 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8662 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8663 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8664 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8665
8666 // exit hover when pointer goes away
8667 processId(mapper, -1);
8668 processSync(mapper);
8669 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8670 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8671 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8672 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8673}
8674
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008675/**
8676 * Set the input device port <--> display port associations, and check that the
8677 * events are routed to the display that matches the display port.
8678 * This can be checked by looking at the displayId of the resulting NotifyMotionArgs.
8679 */
8680TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayPort) {
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008681 const std::string usb2 = "USB2";
8682 const uint8_t hdmi1 = 0;
8683 const uint8_t hdmi2 = 1;
8684 const std::string secondaryUniqueId = "uniqueId2";
Michael Wrightfe3de7d2020-07-02 19:05:30 +01008685 constexpr ViewportType type = ViewportType::EXTERNAL;
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008686
8687 addConfigurationProperty("touch.deviceType", "touchScreen");
8688 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008689 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008690
8691 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
8692 mFakePolicy->addInputPortAssociation(usb2, hdmi2);
8693
8694 // We are intentionally not adding the viewport for display 1 yet. Since the port association
8695 // for this input device is specified, and the matching viewport is not present,
8696 // the input device should be disabled (at the mapper level).
8697
8698 // Add viewport for display 2 on hdmi2
8699 prepareSecondaryDisplay(type, hdmi2);
8700 // Send a touch event
8701 processPosition(mapper, 100, 100);
8702 processSync(mapper);
8703 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
8704
8705 // Add viewport for display 1 on hdmi1
Michael Wrighta9cf4192022-12-01 23:46:39 +00008706 prepareDisplay(ui::ROTATION_0, hdmi1);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008707 // Send a touch event again
8708 processPosition(mapper, 100, 100);
8709 processSync(mapper);
8710
8711 NotifyMotionArgs args;
8712 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8713 ASSERT_EQ(DISPLAY_ID, args.displayId);
8714}
Michael Wrightd02c5b62014-02-10 15:10:22 -08008715
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008716TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayUniqueId) {
8717 addConfigurationProperty("touch.deviceType", "touchScreen");
8718 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008719 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008720
8721 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID);
8722
Michael Wrighta9cf4192022-12-01 23:46:39 +00008723 prepareDisplay(ui::ROTATION_0);
8724 prepareVirtualDisplay(ui::ROTATION_0);
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008725
8726 // Send a touch event
8727 processPosition(mapper, 100, 100);
8728 processSync(mapper);
8729
8730 NotifyMotionArgs args;
8731 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8732 ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId);
8733}
8734
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008735TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01008736 prepareSecondaryDisplay(ViewportType::EXTERNAL);
Garfield Tan888a6a42020-01-09 11:39:16 -08008737
Michael Wrighta9cf4192022-12-01 23:46:39 +00008738 prepareDisplay(ui::ROTATION_0);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008739 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008740 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008741
Josep del Río2d8c79a2023-01-23 19:33:50 +00008742 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008743
8744 NotifyMotionArgs motionArgs;
8745 processPosition(mapper, 100, 100);
8746 processSync(mapper);
8747
8748 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8749 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008750 ASSERT_EQ(ui::LogicalDisplayId::INVALID, motionArgs.displayId);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008751}
8752
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008753/**
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008754 * Ensure that the readTime is set to the SYN_REPORT value when processing touch events.
8755 */
8756TEST_F(MultiTouchInputMapperTest, Process_SendsReadTime) {
8757 addConfigurationProperty("touch.deviceType", "touchScreen");
8758 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008759 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008760
Michael Wrighta9cf4192022-12-01 23:46:39 +00008761 prepareDisplay(ui::ROTATION_0);
Harry Cutts33476232023-01-30 19:57:29 +00008762 process(mapper, 10, /*readTime=*/11, EV_ABS, ABS_MT_TRACKING_ID, 1);
8763 process(mapper, 15, /*readTime=*/16, EV_ABS, ABS_MT_POSITION_X, 100);
8764 process(mapper, 20, /*readTime=*/21, EV_ABS, ABS_MT_POSITION_Y, 100);
8765 process(mapper, 25, /*readTime=*/26, EV_SYN, SYN_REPORT, 0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008766
8767 NotifyMotionArgs args;
8768 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8769 ASSERT_EQ(26, args.readTime);
8770
Harry Cutts33476232023-01-30 19:57:29 +00008771 process(mapper, 30, /*readTime=*/31, EV_ABS, ABS_MT_POSITION_X, 110);
8772 process(mapper, 30, /*readTime=*/32, EV_ABS, ABS_MT_POSITION_Y, 220);
8773 process(mapper, 30, /*readTime=*/33, EV_SYN, SYN_REPORT, 0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008774
8775 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8776 ASSERT_EQ(33, args.readTime);
8777}
8778
8779/**
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008780 * When the viewport is not active (isActive=false), the touch mapper should be disabled and the
8781 * events should not be delivered to the listener.
8782 */
8783TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreDropped) {
8784 addConfigurationProperty("touch.deviceType", "touchScreen");
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008785 // Don't set touch.enableForInactiveViewport to verify the default behavior.
Michael Wrighta9cf4192022-12-01 23:46:39 +00008786 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008787 /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008788 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008789 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008790 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008791
8792 NotifyMotionArgs motionArgs;
8793 processPosition(mapper, 100, 100);
8794 processSync(mapper);
8795
8796 mFakeListener->assertNotifyMotionWasNotCalled();
8797}
8798
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008799/**
8800 * When the viewport is not active (isActive=false) and touch.enableForInactiveViewport is true,
8801 * the touch mapper can process the events and the events can be delivered to the listener.
8802 */
8803TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreProcessed) {
8804 addConfigurationProperty("touch.deviceType", "touchScreen");
8805 addConfigurationProperty("touch.enableForInactiveViewport", "1");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008806 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008807 /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008808 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008809 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008810 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008811
8812 NotifyMotionArgs motionArgs;
8813 processPosition(mapper, 100, 100);
8814 processSync(mapper);
8815
8816 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8817 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8818}
8819
Josh Thielene986aed2023-06-01 14:17:30 +00008820/**
8821 * When the viewport is deactivated (isActive transitions from true to false),
8822 * and touch.enableForInactiveViewport is false, touches prior to the transition
8823 * should be cancelled.
8824 */
Garfield Tanc734e4f2021-01-15 20:01:39 -08008825TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_AbortTouches) {
8826 addConfigurationProperty("touch.deviceType", "touchScreen");
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008827 addConfigurationProperty("touch.enableForInactiveViewport", "0");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008828 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008829 /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008830 std::optional<DisplayViewport> optionalDisplayViewport =
8831 mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
8832 ASSERT_TRUE(optionalDisplayViewport.has_value());
8833 DisplayViewport displayViewport = *optionalDisplayViewport;
8834
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008835 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008836 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008837 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Garfield Tanc734e4f2021-01-15 20:01:39 -08008838
8839 // Finger down
8840 int32_t x = 100, y = 100;
8841 processPosition(mapper, x, y);
8842 processSync(mapper);
8843
8844 NotifyMotionArgs motionArgs;
8845 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8846 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8847
8848 // Deactivate display viewport
8849 displayViewport.isActive = false;
8850 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008851 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008852
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008853 // The ongoing touch should be canceled immediately
8854 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8855 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
8856
8857 // Finger move is ignored
Garfield Tanc734e4f2021-01-15 20:01:39 -08008858 x += 10, y += 10;
8859 processPosition(mapper, x, y);
8860 processSync(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008861 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
Garfield Tanc734e4f2021-01-15 20:01:39 -08008862
8863 // Reactivate display viewport
8864 displayViewport.isActive = true;
8865 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008866 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008867
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008868 // Finger move again starts new gesture
Garfield Tanc734e4f2021-01-15 20:01:39 -08008869 x += 10, y += 10;
8870 processPosition(mapper, x, y);
8871 processSync(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008872 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8873 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008874}
8875
Josh Thielene986aed2023-06-01 14:17:30 +00008876/**
8877 * When the viewport is deactivated (isActive transitions from true to false),
8878 * and touch.enableForInactiveViewport is true, touches prior to the transition
8879 * should not be cancelled.
8880 */
8881TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_TouchesNotAborted) {
8882 addConfigurationProperty("touch.deviceType", "touchScreen");
8883 addConfigurationProperty("touch.enableForInactiveViewport", "1");
8884 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
8885 /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
8886 std::optional<DisplayViewport> optionalDisplayViewport =
8887 mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
8888 ASSERT_TRUE(optionalDisplayViewport.has_value());
8889 DisplayViewport displayViewport = *optionalDisplayViewport;
8890
8891 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8892 prepareAxes(POSITION);
8893 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
8894
8895 // Finger down
8896 int32_t x = 100, y = 100;
8897 processPosition(mapper, x, y);
8898 processSync(mapper);
8899 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8900 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
8901
8902 // Deactivate display viewport
8903 displayViewport.isActive = false;
8904 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
8905 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8906
8907 // The ongoing touch should not be canceled
8908 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
8909
8910 // Finger move is not ignored
8911 x += 10, y += 10;
8912 processPosition(mapper, x, y);
8913 processSync(mapper);
8914 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8915 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
8916
8917 // Reactivate display viewport
8918 displayViewport.isActive = true;
8919 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
8920 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8921
8922 // Finger move continues and does not start new gesture
8923 x += 10, y += 10;
8924 processPosition(mapper, x, y);
8925 processSync(mapper);
8926 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8927 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
8928}
8929
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008930TEST_F(MultiTouchInputMapperTest, VideoFrames_ReceivedByListener) {
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008931 prepareAxes(POSITION);
8932 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008933 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00008934 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008935
8936 NotifyMotionArgs motionArgs;
8937 // Unrotated video frame
8938 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8939 std::vector<TouchVideoFrame> frames{frame};
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008940 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008941 processPosition(mapper, 100, 200);
8942 processSync(mapper);
8943 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8944 ASSERT_EQ(frames, motionArgs.videoFrames);
8945
8946 // Subsequent touch events should not have any videoframes
8947 // This is implemented separately in FakeEventHub,
8948 // but that should match the behaviour of TouchVideoDevice.
8949 processPosition(mapper, 200, 200);
8950 processSync(mapper);
8951 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8952 ASSERT_EQ(std::vector<TouchVideoFrame>(), motionArgs.videoFrames);
8953}
8954
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008955TEST_F(MultiTouchInputMapperTest, VideoFrames_AreNotRotated) {
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008956 prepareAxes(POSITION);
8957 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00008958 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008959 // Unrotated video frame
8960 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8961 NotifyMotionArgs motionArgs;
8962
8963 // Test all 4 orientations
Michael Wrighta9cf4192022-12-01 23:46:39 +00008964 for (ui::Rotation orientation : ftl::enum_range<ui::Rotation>()) {
Harry Cuttsc57cd3c2024-04-24 13:52:55 +00008965 SCOPED_TRACE(StringPrintf("Orientation %s", ftl::enum_string(orientation).c_str()));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008966 clearViewports();
8967 prepareDisplay(orientation);
8968 std::vector<TouchVideoFrame> frames{frame};
8969 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
8970 processPosition(mapper, 100, 200);
8971 processSync(mapper);
8972 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8973 ASSERT_EQ(frames, motionArgs.videoFrames);
8974 }
8975}
8976
8977TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_AreRotated) {
8978 prepareAxes(POSITION);
8979 addConfigurationProperty("touch.deviceType", "touchScreen");
8980 // Since InputReader works in the un-rotated coordinate space, only devices that are not
8981 // orientation-aware are affected by display rotation.
8982 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00008983 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008984 // Unrotated video frame
8985 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8986 NotifyMotionArgs motionArgs;
8987
8988 // Test all 4 orientations
Michael Wrighta9cf4192022-12-01 23:46:39 +00008989 for (ui::Rotation orientation : ftl::enum_range<ui::Rotation>()) {
Harry Cuttsc57cd3c2024-04-24 13:52:55 +00008990 SCOPED_TRACE(StringPrintf("Orientation %s", ftl::enum_string(orientation).c_str()));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008991 clearViewports();
8992 prepareDisplay(orientation);
8993 std::vector<TouchVideoFrame> frames{frame};
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008994 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008995 processPosition(mapper, 100, 200);
8996 processSync(mapper);
8997 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008998 // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction
8999 // compared to the display. This is so that when the window transform (which contains the
9000 // display rotation) is applied later by InputDispatcher, the coordinates end up in the
9001 // window's coordinate space.
9002 frames[0].rotate(getInverseRotation(orientation));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009003 ASSERT_EQ(frames, motionArgs.videoFrames);
lilinnan687e58f2022-07-19 16:00:50 +08009004
9005 // Release finger.
9006 processSync(mapper);
9007 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009008 }
9009}
9010
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009011TEST_F(MultiTouchInputMapperTest, VideoFrames_MultipleFramesAreNotRotated) {
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009012 prepareAxes(POSITION);
9013 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00009014 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009015 // Unrotated video frames. There's no rule that they must all have the same dimensions,
9016 // so mix these.
9017 TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
9018 TouchVideoFrame frame2(3, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {1, 3});
9019 TouchVideoFrame frame3(2, 2, {10, 20, 10, 0}, {1, 4});
9020 std::vector<TouchVideoFrame> frames{frame1, frame2, frame3};
9021 NotifyMotionArgs motionArgs;
9022
Michael Wrighta9cf4192022-12-01 23:46:39 +00009023 prepareDisplay(ui::ROTATION_90);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009024 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009025 processPosition(mapper, 100, 200);
9026 processSync(mapper);
9027 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009028 ASSERT_EQ(frames, motionArgs.videoFrames);
9029}
9030
9031TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_MultipleFramesAreRotated) {
9032 prepareAxes(POSITION);
9033 addConfigurationProperty("touch.deviceType", "touchScreen");
9034 // Since InputReader works in the un-rotated coordinate space, only devices that are not
9035 // orientation-aware are affected by display rotation.
9036 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00009037 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009038 // Unrotated video frames. There's no rule that they must all have the same dimensions,
9039 // so mix these.
9040 TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
9041 TouchVideoFrame frame2(3, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {1, 3});
9042 TouchVideoFrame frame3(2, 2, {10, 20, 10, 0}, {1, 4});
9043 std::vector<TouchVideoFrame> frames{frame1, frame2, frame3};
9044 NotifyMotionArgs motionArgs;
9045
Michael Wrighta9cf4192022-12-01 23:46:39 +00009046 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009047 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
9048 processPosition(mapper, 100, 200);
9049 processSync(mapper);
9050 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9051 std::for_each(frames.begin(), frames.end(), [](TouchVideoFrame& frame) {
9052 // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction
9053 // compared to the display. This is so that when the window transform (which contains the
9054 // display rotation) is applied later by InputDispatcher, the coordinates end up in the
9055 // window's coordinate space.
Michael Wrighta9cf4192022-12-01 23:46:39 +00009056 frame.rotate(getInverseRotation(ui::ROTATION_90));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009057 });
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009058 ASSERT_EQ(frames, motionArgs.videoFrames);
9059}
9060
Arthur Hung9da14732019-09-02 16:16:58 +08009061/**
9062 * If we had defined port associations, but the viewport is not ready, the touch device would be
9063 * expected to be disabled, and it should be enabled after the viewport has found.
9064 */
9065TEST_F(MultiTouchInputMapperTest, Configure_EnabledForAssociatedDisplay) {
Arthur Hung9da14732019-09-02 16:16:58 +08009066 constexpr uint8_t hdmi2 = 1;
9067 const std::string secondaryUniqueId = "uniqueId2";
Michael Wrightfe3de7d2020-07-02 19:05:30 +01009068 constexpr ViewportType type = ViewportType::EXTERNAL;
Arthur Hung9da14732019-09-02 16:16:58 +08009069
9070 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi2);
9071
9072 addConfigurationProperty("touch.deviceType", "touchScreen");
9073 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00009074 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung9da14732019-09-02 16:16:58 +08009075
9076 ASSERT_EQ(mDevice->isEnabled(), false);
9077
9078 // Add display on hdmi2, the device should be enabled and can receive touch event.
9079 prepareSecondaryDisplay(type, hdmi2);
9080 ASSERT_EQ(mDevice->isEnabled(), true);
9081
9082 // Send a touch event.
9083 processPosition(mapper, 100, 100);
9084 processSync(mapper);
9085
9086 NotifyMotionArgs args;
9087 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9088 ASSERT_EQ(SECONDARY_DISPLAY_ID, args.displayId);
9089}
9090
Arthur Hung421eb1c2020-01-16 00:09:42 +08009091TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleSingleTouch) {
Arthur Hung421eb1c2020-01-16 00:09:42 +08009092 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009093 prepareDisplay(ui::ROTATION_0);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009094 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009095 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung421eb1c2020-01-16 00:09:42 +08009096
9097 NotifyMotionArgs motionArgs;
9098
9099 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
9100 // finger down
9101 processId(mapper, 1);
9102 processPosition(mapper, x1, y1);
9103 processSync(mapper);
9104 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9105 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009106 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009107
9108 // finger move
9109 processId(mapper, 1);
9110 processPosition(mapper, x2, y2);
9111 processSync(mapper);
9112 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9113 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009114 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009115
9116 // finger up.
9117 processId(mapper, -1);
9118 processSync(mapper);
9119 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9120 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009121 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009122
9123 // new finger down
9124 processId(mapper, 1);
9125 processPosition(mapper, x3, y3);
9126 processSync(mapper);
9127 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9128 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009129 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009130}
9131
9132/**
arthurhungcc7f9802020-04-30 17:55:40 +08009133 * Test single touch should be canceled when received the MT_TOOL_PALM event, and the following
9134 * MOVE and UP events should be ignored.
Arthur Hung421eb1c2020-01-16 00:09:42 +08009135 */
arthurhungcc7f9802020-04-30 17:55:40 +08009136TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_SinglePointer) {
Arthur Hung421eb1c2020-01-16 00:09:42 +08009137 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009138 prepareDisplay(ui::ROTATION_0);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009139 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009140 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung421eb1c2020-01-16 00:09:42 +08009141
9142 NotifyMotionArgs motionArgs;
9143
9144 // default tool type is finger
9145 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
arthurhungcc7f9802020-04-30 17:55:40 +08009146 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009147 processPosition(mapper, x1, y1);
9148 processSync(mapper);
9149 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9150 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009151 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009152
9153 // Tool changed to MT_TOOL_PALM expect sending the cancel event.
9154 processToolType(mapper, MT_TOOL_PALM);
9155 processSync(mapper);
9156 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9157 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9158
9159 // Ignore the following MOVE and UP events if had detect a palm event.
arthurhungcc7f9802020-04-30 17:55:40 +08009160 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009161 processPosition(mapper, x2, y2);
9162 processSync(mapper);
9163 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9164
9165 // finger up.
arthurhungcc7f9802020-04-30 17:55:40 +08009166 processId(mapper, INVALID_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009167 processSync(mapper);
9168 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9169
9170 // new finger down
arthurhungcc7f9802020-04-30 17:55:40 +08009171 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009172 processToolType(mapper, MT_TOOL_FINGER);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009173 processPosition(mapper, x3, y3);
9174 processSync(mapper);
9175 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9176 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009177 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009178}
9179
arthurhungbf89a482020-04-17 17:37:55 +08009180/**
arthurhungcc7f9802020-04-30 17:55:40 +08009181 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event from some finger,
9182 * and the rest active fingers could still be allowed to receive the events
arthurhungbf89a482020-04-17 17:37:55 +08009183 */
arthurhungcc7f9802020-04-30 17:55:40 +08009184TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_TwoPointers) {
arthurhungbf89a482020-04-17 17:37:55 +08009185 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009186 prepareDisplay(ui::ROTATION_0);
arthurhungbf89a482020-04-17 17:37:55 +08009187 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009188 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungbf89a482020-04-17 17:37:55 +08009189
9190 NotifyMotionArgs motionArgs;
9191
9192 // default tool type is finger
arthurhungcc7f9802020-04-30 17:55:40 +08009193 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220;
9194 processId(mapper, FIRST_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009195 processPosition(mapper, x1, y1);
9196 processSync(mapper);
9197 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9198 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009199 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungbf89a482020-04-17 17:37:55 +08009200
9201 // Second finger down.
arthurhungcc7f9802020-04-30 17:55:40 +08009202 processSlot(mapper, SECOND_SLOT);
9203 processId(mapper, SECOND_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009204 processPosition(mapper, x2, y2);
arthurhungcc7f9802020-04-30 17:55:40 +08009205 processSync(mapper);
9206 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009207 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009208 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009209
9210 // If the tool type of the first finger changes to MT_TOOL_PALM,
9211 // we expect to receive ACTION_POINTER_UP with cancel flag.
9212 processSlot(mapper, FIRST_SLOT);
9213 processId(mapper, FIRST_TRACKING_ID);
9214 processToolType(mapper, MT_TOOL_PALM);
9215 processSync(mapper);
9216 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009217 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009218 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9219
9220 // The following MOVE events of second finger should be processed.
9221 processSlot(mapper, SECOND_SLOT);
9222 processId(mapper, SECOND_TRACKING_ID);
9223 processPosition(mapper, x2 + 1, y2 + 1);
9224 processSync(mapper);
9225 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9226 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009227 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009228
9229 // First finger up. It used to be in palm mode, and we already generated ACTION_POINTER_UP for
9230 // it. Second finger receive move.
9231 processSlot(mapper, FIRST_SLOT);
9232 processId(mapper, INVALID_TRACKING_ID);
9233 processSync(mapper);
9234 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9235 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009236 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009237
9238 // Second finger keeps moving.
9239 processSlot(mapper, SECOND_SLOT);
9240 processId(mapper, SECOND_TRACKING_ID);
9241 processPosition(mapper, x2 + 2, y2 + 2);
9242 processSync(mapper);
9243 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9244 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009245 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009246
9247 // Second finger up.
9248 processId(mapper, INVALID_TRACKING_ID);
9249 processSync(mapper);
9250 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9251 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9252 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9253}
9254
9255/**
9256 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event, if only 1 finger
9257 * is active, it should send CANCEL after receiving the MT_TOOL_PALM event.
9258 */
9259TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_ShouldCancelWhenAllTouchIsPalm) {
9260 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009261 prepareDisplay(ui::ROTATION_0);
arthurhungcc7f9802020-04-30 17:55:40 +08009262 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009263 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungcc7f9802020-04-30 17:55:40 +08009264
9265 NotifyMotionArgs motionArgs;
9266
9267 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
9268 // First finger down.
9269 processId(mapper, FIRST_TRACKING_ID);
9270 processPosition(mapper, x1, y1);
9271 processSync(mapper);
9272 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9273 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009274 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009275
9276 // Second finger down.
9277 processSlot(mapper, SECOND_SLOT);
9278 processId(mapper, SECOND_TRACKING_ID);
9279 processPosition(mapper, x2, y2);
arthurhungbf89a482020-04-17 17:37:55 +08009280 processSync(mapper);
9281 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009282 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009283 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungbf89a482020-04-17 17:37:55 +08009284
arthurhungcc7f9802020-04-30 17:55:40 +08009285 // If the tool type of the first finger changes to MT_TOOL_PALM,
9286 // we expect to receive ACTION_POINTER_UP with cancel flag.
9287 processSlot(mapper, FIRST_SLOT);
9288 processId(mapper, FIRST_TRACKING_ID);
9289 processToolType(mapper, MT_TOOL_PALM);
9290 processSync(mapper);
9291 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009292 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009293 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9294
9295 // Second finger keeps moving.
9296 processSlot(mapper, SECOND_SLOT);
9297 processId(mapper, SECOND_TRACKING_ID);
9298 processPosition(mapper, x2 + 1, y2 + 1);
9299 processSync(mapper);
9300 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9301 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9302
9303 // second finger becomes palm, receive cancel due to only 1 finger is active.
9304 processId(mapper, SECOND_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009305 processToolType(mapper, MT_TOOL_PALM);
9306 processSync(mapper);
9307 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9308 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9309
arthurhungcc7f9802020-04-30 17:55:40 +08009310 // third finger down.
9311 processSlot(mapper, THIRD_SLOT);
9312 processId(mapper, THIRD_TRACKING_ID);
9313 processToolType(mapper, MT_TOOL_FINGER);
arthurhungbf89a482020-04-17 17:37:55 +08009314 processPosition(mapper, x3, y3);
9315 processSync(mapper);
arthurhungbf89a482020-04-17 17:37:55 +08009316 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9317 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009318 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009319 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009320
9321 // third finger move
9322 processId(mapper, THIRD_TRACKING_ID);
9323 processPosition(mapper, x3 + 1, y3 + 1);
9324 processSync(mapper);
9325 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9326 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9327
9328 // first finger up, third finger receive move.
9329 processSlot(mapper, FIRST_SLOT);
9330 processId(mapper, INVALID_TRACKING_ID);
9331 processSync(mapper);
9332 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9333 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009334 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009335
9336 // second finger up, third finger receive move.
9337 processSlot(mapper, SECOND_SLOT);
9338 processId(mapper, INVALID_TRACKING_ID);
9339 processSync(mapper);
9340 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9341 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009342 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009343
9344 // third finger up.
9345 processSlot(mapper, THIRD_SLOT);
9346 processId(mapper, INVALID_TRACKING_ID);
9347 processSync(mapper);
9348 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9349 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9350 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9351}
9352
9353/**
9354 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event from some finger,
9355 * and the active finger could still be allowed to receive the events
9356 */
9357TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_KeepFirstPointer) {
9358 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009359 prepareDisplay(ui::ROTATION_0);
arthurhungcc7f9802020-04-30 17:55:40 +08009360 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009361 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungcc7f9802020-04-30 17:55:40 +08009362
9363 NotifyMotionArgs motionArgs;
9364
9365 // default tool type is finger
9366 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220;
9367 processId(mapper, FIRST_TRACKING_ID);
9368 processPosition(mapper, x1, y1);
9369 processSync(mapper);
9370 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9371 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009372 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009373
9374 // Second finger down.
9375 processSlot(mapper, SECOND_SLOT);
9376 processId(mapper, SECOND_TRACKING_ID);
9377 processPosition(mapper, x2, y2);
9378 processSync(mapper);
9379 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009380 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009381 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009382
9383 // If the tool type of the second finger changes to MT_TOOL_PALM,
9384 // we expect to receive ACTION_POINTER_UP with cancel flag.
9385 processId(mapper, SECOND_TRACKING_ID);
9386 processToolType(mapper, MT_TOOL_PALM);
9387 processSync(mapper);
9388 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009389 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009390 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9391
9392 // The following MOVE event should be processed.
9393 processSlot(mapper, FIRST_SLOT);
9394 processId(mapper, FIRST_TRACKING_ID);
9395 processPosition(mapper, x1 + 1, y1 + 1);
9396 processSync(mapper);
9397 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9398 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009399 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009400
9401 // second finger up.
9402 processSlot(mapper, SECOND_SLOT);
9403 processId(mapper, INVALID_TRACKING_ID);
9404 processSync(mapper);
9405 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9406 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9407
9408 // first finger keep moving
9409 processSlot(mapper, FIRST_SLOT);
9410 processId(mapper, FIRST_TRACKING_ID);
9411 processPosition(mapper, x1 + 2, y1 + 2);
9412 processSync(mapper);
9413 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9414 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9415
9416 // first finger up.
9417 processId(mapper, INVALID_TRACKING_ID);
9418 processSync(mapper);
9419 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9420 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9421 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
arthurhungbf89a482020-04-17 17:37:55 +08009422}
9423
Arthur Hung9ad18942021-06-19 02:04:46 +00009424/**
9425 * Test multi-touch should sent ACTION_POINTER_UP/ACTION_UP when received the INVALID_TRACKING_ID,
9426 * to prevent the driver side may send unexpected data after set tracking id as INVALID_TRACKING_ID
9427 * cause slot be valid again.
9428 */
9429TEST_F(MultiTouchInputMapperTest, Process_MultiTouch_WithInvalidTrackingId) {
9430 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009431 prepareDisplay(ui::ROTATION_0);
Arthur Hung9ad18942021-06-19 02:04:46 +00009432 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009433 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung9ad18942021-06-19 02:04:46 +00009434
9435 NotifyMotionArgs motionArgs;
9436
9437 constexpr int32_t x1 = 100, y1 = 200, x2 = 0, y2 = 0;
9438 // First finger down.
9439 processId(mapper, FIRST_TRACKING_ID);
9440 processPosition(mapper, x1, y1);
9441 processPressure(mapper, RAW_PRESSURE_MAX);
9442 processSync(mapper);
9443 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9444 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009445 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009446
9447 // First finger move.
9448 processId(mapper, FIRST_TRACKING_ID);
9449 processPosition(mapper, x1 + 1, y1 + 1);
9450 processPressure(mapper, RAW_PRESSURE_MAX);
9451 processSync(mapper);
9452 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9453 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009454 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009455
9456 // Second finger down.
9457 processSlot(mapper, SECOND_SLOT);
9458 processId(mapper, SECOND_TRACKING_ID);
9459 processPosition(mapper, x2, y2);
9460 processPressure(mapper, RAW_PRESSURE_MAX);
9461 processSync(mapper);
9462 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009463 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009464 ASSERT_EQ(uint32_t(2), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009465
9466 // second finger up with some unexpected data.
9467 processSlot(mapper, SECOND_SLOT);
9468 processId(mapper, INVALID_TRACKING_ID);
9469 processPosition(mapper, x2, y2);
9470 processSync(mapper);
9471 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009472 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009473 ASSERT_EQ(uint32_t(2), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009474
9475 // first finger up with some unexpected data.
9476 processSlot(mapper, FIRST_SLOT);
9477 processId(mapper, INVALID_TRACKING_ID);
9478 processPosition(mapper, x2, y2);
9479 processPressure(mapper, RAW_PRESSURE_MAX);
9480 processSync(mapper);
9481 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9482 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009483 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009484}
9485
Arpit Singh4b4a4572023-11-24 18:19:56 +00009486TEST_F(MultiTouchInputMapperTest, Reset_RepopulatesMultiTouchState) {
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009487 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009488 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009489 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009490 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009491
9492 // First finger down.
Arpit Singh4b4a4572023-11-24 18:19:56 +00009493 constexpr int32_t x1 = 100, y1 = 200, x2 = 300, y2 = 400;
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009494 processId(mapper, FIRST_TRACKING_ID);
Arpit Singh4b4a4572023-11-24 18:19:56 +00009495 processPosition(mapper, x1, y1);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009496 processPressure(mapper, RAW_PRESSURE_MAX);
9497 processSync(mapper);
9498 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9499 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
9500
9501 // Second finger down.
9502 processSlot(mapper, SECOND_SLOT);
9503 processId(mapper, SECOND_TRACKING_ID);
Arpit Singh4b4a4572023-11-24 18:19:56 +00009504 processPosition(mapper, x2, y2);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009505 processPressure(mapper, RAW_PRESSURE_MAX);
9506 processSync(mapper);
9507 ASSERT_NO_FATAL_FAILURE(
9508 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(ACTION_POINTER_1_DOWN)));
9509
Arpit Singh4b4a4572023-11-24 18:19:56 +00009510 // Set MT Slot state to be repopulated for the required slots
9511 std::vector<int32_t> mtSlotValues(RAW_SLOT_MAX + 1, -1);
9512 mtSlotValues[0] = FIRST_TRACKING_ID;
9513 mtSlotValues[1] = SECOND_TRACKING_ID;
9514 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_TRACKING_ID, mtSlotValues);
9515
9516 mtSlotValues[0] = x1;
9517 mtSlotValues[1] = x2;
9518 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_POSITION_X, mtSlotValues);
9519
9520 mtSlotValues[0] = y1;
9521 mtSlotValues[1] = y2;
9522 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_POSITION_Y, mtSlotValues);
9523
9524 mtSlotValues[0] = RAW_PRESSURE_MAX;
9525 mtSlotValues[1] = RAW_PRESSURE_MAX;
9526 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_PRESSURE, mtSlotValues);
9527
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009528 // Reset the mapper. When the mapper is reset, we expect the current multi-touch state to be
Arpit Singh4b4a4572023-11-24 18:19:56 +00009529 // repopulated. Resetting should cancel the ongoing gesture.
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00009530 resetMapper(mapper, ARBITRARY_TIME);
9531 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9532 WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009533
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009534 // Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
9535 // the existing touch state to generate a down event.
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009536 processPosition(mapper, 301, 302);
9537 processSync(mapper);
9538 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9539 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPressure(1.f))));
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009540 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9541 AllOf(WithMotionAction(ACTION_POINTER_1_DOWN), WithPressure(1.f))));
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009542
9543 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9544}
9545
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009546TEST_F(MultiTouchInputMapperTest, Reset_PreservesLastTouchState_NoPointersDown) {
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009547 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009548 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009549 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009550 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009551
9552 // First finger touches down and releases.
9553 processId(mapper, FIRST_TRACKING_ID);
9554 processPosition(mapper, 100, 200);
9555 processPressure(mapper, RAW_PRESSURE_MAX);
9556 processSync(mapper);
9557 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9558 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
9559 processId(mapper, INVALID_TRACKING_ID);
9560 processSync(mapper);
9561 ASSERT_NO_FATAL_FAILURE(
9562 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
9563
9564 // Reset the mapper. When the mapper is reset, we expect it to restore the latest
9565 // raw state where no pointers are down.
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00009566 resetMapper(mapper, ARBITRARY_TIME);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009567 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9568
9569 // Send an empty sync frame. Since there are no pointers, no events are generated.
9570 processSync(mapper);
9571 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9572}
9573
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009574TEST_F(MultiTouchInputMapperTest, StylusSourceIsAddedDynamicallyFromToolType) {
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009575 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009576 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009577 prepareAxes(POSITION | ID | SLOT | PRESSURE | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009578 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009579 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009580
9581 // Even if the device supports reporting the ABS_MT_TOOL_TYPE axis, which could give it the
9582 // ability to report MT_TOOL_PEN, we do not report the device as coming from a stylus source.
9583 // Due to limitations in the evdev protocol, we cannot say for certain that a device is capable
9584 // of reporting stylus events just because it supports ABS_MT_TOOL_TYPE.
9585 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
9586
9587 // However, if the device ever ends up reporting an event with MT_TOOL_PEN, it should be
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009588 // reported with the stylus source.
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009589 processId(mapper, FIRST_TRACKING_ID);
9590 processToolType(mapper, MT_TOOL_PEN);
9591 processPosition(mapper, 100, 200);
9592 processPressure(mapper, RAW_PRESSURE_MAX);
9593 processSync(mapper);
9594 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9595 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
9596 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009597 WithToolType(ToolType::STYLUS))));
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009598
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009599 // Now that we know the device supports styluses, ensure that the device is re-configured with
9600 // the stylus source.
9601 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, mapper.getSources());
9602 {
9603 const auto& devices = mReader->getInputDevices();
9604 auto deviceInfo =
9605 std::find_if(devices.begin(), devices.end(),
9606 [](const InputDeviceInfo& info) { return info.getId() == DEVICE_ID; });
9607 LOG_ALWAYS_FATAL_IF(deviceInfo == devices.end(), "Cannot find InputDevice");
9608 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, deviceInfo->getSources());
9609 }
9610
9611 // Ensure the device was not reset to prevent interruptions of any ongoing gestures.
9612 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
9613
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009614 processId(mapper, INVALID_TRACKING_ID);
9615 processSync(mapper);
9616 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9617 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
9618 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009619 WithToolType(ToolType::STYLUS))));
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009620}
9621
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009622// --- MultiTouchInputMapperTest_ExternalDevice ---
9623
9624class MultiTouchInputMapperTest_ExternalDevice : public MultiTouchInputMapperTest {
9625protected:
Chris Yea52ade12020-08-27 16:49:20 -07009626 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL); }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009627};
9628
9629/**
9630 * Expect fallback to internal viewport if device is external and external viewport is not present.
9631 */
9632TEST_F(MultiTouchInputMapperTest_ExternalDevice, Viewports_Fallback) {
9633 prepareAxes(POSITION);
9634 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009635 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00009636 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009637
9638 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
9639
9640 NotifyMotionArgs motionArgs;
9641
9642 // Expect the event to be sent to the internal viewport,
9643 // because an external viewport is not present.
9644 processPosition(mapper, 100, 100);
9645 processSync(mapper);
9646 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009647 ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, motionArgs.displayId);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009648
9649 // Expect the event to be sent to the external viewport if it is present.
Michael Wrightfe3de7d2020-07-02 19:05:30 +01009650 prepareSecondaryDisplay(ViewportType::EXTERNAL);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009651 processPosition(mapper, 100, 100);
9652 processSync(mapper);
9653 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9654 ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
9655}
Arthur Hung4197f6b2020-03-16 15:39:59 +08009656
Prabir Pradhan3ed7e352024-05-03 23:59:43 +00009657// TODO(b/281840344): Remove the test when the old touchpad stack is removed. It is currently
9658// unclear what the behavior of the touchpad logic in TouchInputMapper should do after the
9659// PointerChoreographer refactor.
9660TEST_F(MultiTouchInputMapperTest, DISABLED_Process_TouchpadPointer) {
Harry Cutts8722be92024-04-05 14:46:05 +00009661 // prepare device
Michael Wrighta9cf4192022-12-01 23:46:39 +00009662 prepareDisplay(ui::ROTATION_0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009663 prepareAxes(POSITION | ID | SLOT);
9664 mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
9665 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00009666 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009667 // run uncaptured pointer tests - pushes out generic events
9668 // FINGER 0 DOWN
9669 processId(mapper, 3);
9670 processPosition(mapper, 100, 100);
9671 processKey(mapper, BTN_TOUCH, 1);
9672 processSync(mapper);
9673
9674 // start at (100,100), cursor should be at (0,0) * scale
9675 NotifyMotionArgs args;
9676 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9677 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
9678 ASSERT_NO_FATAL_FAILURE(
9679 assertPointerCoords(args.pointerCoords[0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
9680
9681 // FINGER 0 MOVE
9682 processPosition(mapper, 200, 200);
9683 processSync(mapper);
9684
9685 // compute scaling to help with touch position checking
9686 float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
9687 float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
9688 float scale =
9689 mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
9690
9691 // translate from (100,100) -> (200,200), cursor should have changed to (100,100) * scale)
9692 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9693 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
9694 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], 100 * scale, 100 * scale, 0,
9695 0, 0, 0, 0, 0, 0, 0));
LiZhihong758eb562022-11-03 15:28:29 +08009696
9697 // BUTTON DOWN
9698 processKey(mapper, BTN_LEFT, 1);
9699 processSync(mapper);
9700
9701 // touchinputmapper design sends a move before button press
9702 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9703 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
9704 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9705 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, args.action);
9706
9707 // BUTTON UP
9708 processKey(mapper, BTN_LEFT, 0);
9709 processSync(mapper);
9710
9711 // touchinputmapper design sends a move after button release
9712 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9713 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, args.action);
9714 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9715 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009716}
9717
Harry Cutts8722be92024-04-05 14:46:05 +00009718TEST_F(MultiTouchInputMapperTest, Touchpad_GetSources) {
Michael Wrighta9cf4192022-12-01 23:46:39 +00009719 prepareDisplay(ui::ROTATION_0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009720 prepareAxes(POSITION | ID | SLOT);
9721 mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
Hiroki Sato25040232024-02-22 17:21:22 +09009722 mFakePolicy->setPointerCapture(/*window=*/nullptr);
Arpit Singha8c236b2023-04-25 13:56:05 +00009723 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009724
Josep del Río2d8c79a2023-01-23 19:33:50 +00009725 // uncaptured touchpad should be a pointer device
9726 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009727}
9728
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009729// --- BluetoothMultiTouchInputMapperTest ---
9730
9731class BluetoothMultiTouchInputMapperTest : public MultiTouchInputMapperTest {
9732protected:
9733 void SetUp() override {
9734 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL, BUS_BLUETOOTH);
9735 }
9736};
9737
9738TEST_F(BluetoothMultiTouchInputMapperTest, TimestampSmoothening) {
9739 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009740 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009741 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009742 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009743
9744 nsecs_t kernelEventTime = ARBITRARY_TIME;
9745 nsecs_t expectedEventTime = ARBITRARY_TIME;
9746 // Touch down.
9747 processId(mapper, FIRST_TRACKING_ID);
9748 processPosition(mapper, 100, 200);
9749 processPressure(mapper, RAW_PRESSURE_MAX);
9750 processSync(mapper, ARBITRARY_TIME);
9751 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9752 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithEventTime(ARBITRARY_TIME))));
9753
9754 // Process several events that come in quick succession, according to their timestamps.
9755 for (int i = 0; i < 3; i++) {
9756 constexpr static nsecs_t delta = ms2ns(1);
9757 static_assert(delta < MIN_BLUETOOTH_TIMESTAMP_DELTA);
9758 kernelEventTime += delta;
9759 expectedEventTime += MIN_BLUETOOTH_TIMESTAMP_DELTA;
9760
9761 processPosition(mapper, 101 + i, 201 + i);
9762 processSync(mapper, kernelEventTime);
9763 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9764 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
9765 WithEventTime(expectedEventTime))));
9766 }
9767
9768 // Release the touch.
9769 processId(mapper, INVALID_TRACKING_ID);
9770 processPressure(mapper, RAW_PRESSURE_MIN);
9771 processSync(mapper, ARBITRARY_TIME + ms2ns(50));
9772 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9773 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
9774 WithEventTime(ARBITRARY_TIME + ms2ns(50)))));
9775}
9776
9777// --- MultiTouchPointerModeTest ---
9778
HQ Liue6983c72022-04-19 22:14:56 +00009779class MultiTouchPointerModeTest : public MultiTouchInputMapperTest {
9780protected:
9781 float mPointerMovementScale;
9782 float mPointerXZoomScale;
9783 void preparePointerMode(int xAxisResolution, int yAxisResolution) {
9784 addConfigurationProperty("touch.deviceType", "pointer");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009785 prepareDisplay(ui::ROTATION_0);
HQ Liue6983c72022-04-19 22:14:56 +00009786
9787 prepareAxes(POSITION);
9788 prepareAbsoluteAxisResolution(xAxisResolution, yAxisResolution);
9789 // In order to enable swipe and freeform gesture in pointer mode, pointer capture
9790 // needs to be disabled, and the pointer gesture needs to be enabled.
Hiroki Sato25040232024-02-22 17:21:22 +09009791 mFakePolicy->setPointerCapture(/*window=*/nullptr);
HQ Liue6983c72022-04-19 22:14:56 +00009792 mFakePolicy->setPointerGestureEnabled(true);
HQ Liue6983c72022-04-19 22:14:56 +00009793
9794 float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
9795 float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
9796 mPointerMovementScale =
9797 mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
9798 mPointerXZoomScale =
9799 mFakePolicy->getPointerGestureZoomSpeedRatio() * displayDiagonal / rawDiagonal;
9800 }
9801
9802 void prepareAbsoluteAxisResolution(int xAxisResolution, int yAxisResolution) {
9803 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX,
9804 /*flat*/ 0,
9805 /*fuzz*/ 0, /*resolution*/ xAxisResolution);
9806 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX,
9807 /*flat*/ 0,
9808 /*fuzz*/ 0, /*resolution*/ yAxisResolution);
9809 }
9810};
9811
9812/**
9813 * Two fingers down on a pointer mode touch pad. The width
9814 * of the two finger is larger than 1/4 of the touch pack diagnal length. However, it
9815 * is smaller than the fixed min physical length 30mm. Two fingers' distance must
9816 * be greater than the both value to be freeform gesture, so that after two
9817 * fingers start to move downwards, the gesture should be swipe.
9818 */
9819TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthSwipe) {
9820 // The min freeform gesture width is 25units/mm x 30mm = 750
9821 // which is greater than fraction of the diagnal length of the touchpad (349).
9822 // Thus, MaxSwipWidth is 750.
Harry Cutts33476232023-01-30 19:57:29 +00009823 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +00009824 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009825 NotifyMotionArgs motionArgs;
9826
9827 // Two fingers down at once.
9828 // The two fingers are 450 units apart, expects the current gesture to be PRESS
9829 // Pointer's initial position is used the [0,0] coordinate.
9830 int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125;
9831
9832 processId(mapper, FIRST_TRACKING_ID);
9833 processPosition(mapper, x1, y1);
9834 processMTSync(mapper);
9835 processId(mapper, SECOND_TRACKING_ID);
9836 processPosition(mapper, x2, y2);
9837 processMTSync(mapper);
9838 processSync(mapper);
9839
9840 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009841 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009842 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009843 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009844 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009845 ASSERT_NO_FATAL_FAILURE(
9846 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9847
9848 // It should be recognized as a SWIPE gesture when two fingers start to move down,
9849 // that there should be 1 pointer.
9850 int32_t movingDistance = 200;
9851 y1 += movingDistance;
9852 y2 += movingDistance;
9853
9854 processId(mapper, FIRST_TRACKING_ID);
9855 processPosition(mapper, x1, y1);
9856 processMTSync(mapper);
9857 processId(mapper, SECOND_TRACKING_ID);
9858 processPosition(mapper, x2, y2);
9859 processMTSync(mapper);
9860 processSync(mapper);
9861
9862 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009863 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009864 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009865 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009866 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009867 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
9868 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9869 0, 0, 0, 0));
9870}
9871
9872/**
9873 * Two fingers down on a pointer mode touch pad. The width of the two finger is larger
9874 * than the minimum freeform gesture width, 30mm. However, it is smaller than 1/4 of
9875 * the touch pack diagnal length. Two fingers' distance must be greater than the both
9876 * value to be freeform gesture, so that after two fingers start to move downwards,
9877 * the gesture should be swipe.
9878 */
9879TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthLowResolutionSwipe) {
9880 // The min freeform gesture width is 5units/mm x 30mm = 150
9881 // which is greater than fraction of the diagnal length of the touchpad (349).
9882 // Thus, MaxSwipWidth is the fraction of the diagnal length, 349.
Harry Cutts33476232023-01-30 19:57:29 +00009883 preparePointerMode(/*xResolution=*/5, /*yResolution=*/5);
Arpit Singha8c236b2023-04-25 13:56:05 +00009884 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009885 NotifyMotionArgs motionArgs;
9886
9887 // Two fingers down at once.
9888 // The two fingers are 250 units apart, expects the current gesture to be PRESS
9889 // Pointer's initial position is used the [0,0] coordinate.
9890 int32_t x1 = 100, y1 = 125, x2 = 350, y2 = 125;
9891
9892 processId(mapper, FIRST_TRACKING_ID);
9893 processPosition(mapper, x1, y1);
9894 processMTSync(mapper);
9895 processId(mapper, SECOND_TRACKING_ID);
9896 processPosition(mapper, x2, y2);
9897 processMTSync(mapper);
9898 processSync(mapper);
9899
9900 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009901 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009902 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009903 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009904 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009905 ASSERT_NO_FATAL_FAILURE(
9906 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9907
9908 // It should be recognized as a SWIPE gesture when two fingers start to move down,
9909 // and there should be 1 pointer.
9910 int32_t movingDistance = 200;
9911 y1 += movingDistance;
9912 y2 += movingDistance;
9913
9914 processId(mapper, FIRST_TRACKING_ID);
9915 processPosition(mapper, x1, y1);
9916 processMTSync(mapper);
9917 processId(mapper, SECOND_TRACKING_ID);
9918 processPosition(mapper, x2, y2);
9919 processMTSync(mapper);
9920 processSync(mapper);
9921
9922 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009923 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009924 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009925 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009926 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009927 // New coordinate is the scaled relative coordinate from the initial coordinate.
9928 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
9929 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9930 0, 0, 0, 0));
9931}
9932
9933/**
9934 * Touch the touch pad with two fingers with a distance wider than the minimum freeform
9935 * gesture width and 1/4 of the diagnal length of the touchpad. Expect to receive
9936 * freeform gestures after two fingers start to move downwards.
9937 */
9938TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthFreeform) {
Harry Cutts33476232023-01-30 19:57:29 +00009939 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +00009940 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009941
9942 NotifyMotionArgs motionArgs;
9943
9944 // Two fingers down at once. Wider than the max swipe width.
9945 // The gesture is expected to be PRESS, then transformed to FREEFORM
9946 int32_t x1 = 100, y1 = 125, x2 = 900, y2 = 125;
9947
9948 processId(mapper, FIRST_TRACKING_ID);
9949 processPosition(mapper, x1, y1);
9950 processMTSync(mapper);
9951 processId(mapper, SECOND_TRACKING_ID);
9952 processPosition(mapper, x2, y2);
9953 processMTSync(mapper);
9954 processSync(mapper);
9955
9956 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009957 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009958 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009959 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009960 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009961 // One pointer for PRESS, and its coordinate is used as the origin for pointer coordinates.
9962 ASSERT_NO_FATAL_FAILURE(
9963 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9964
9965 int32_t movingDistance = 200;
9966
9967 // Move two fingers down, expect a cancel event because gesture is changing to freeform,
9968 // then two down events for two pointers.
9969 y1 += movingDistance;
9970 y2 += movingDistance;
9971
9972 processId(mapper, FIRST_TRACKING_ID);
9973 processPosition(mapper, x1, y1);
9974 processMTSync(mapper);
9975 processId(mapper, SECOND_TRACKING_ID);
9976 processPosition(mapper, x2, y2);
9977 processMTSync(mapper);
9978 processSync(mapper);
9979
9980 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9981 // The previous PRESS gesture is cancelled, because it is transformed to freeform
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009982 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009983 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9984 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009985 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009986 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009987 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
9988 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009989 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009990 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009991 ASSERT_EQ(2U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009992 ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN, motionArgs.action & AMOTION_EVENT_ACTION_MASK);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009993 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009994 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009995 // Two pointers' scaled relative coordinates from their initial centroid.
9996 // Initial y coordinates are 0 as y1 and y2 have the same value.
9997 float cookedX1 = (x1 - x2) / 2 * mPointerXZoomScale;
9998 float cookedX2 = (x2 - x1) / 2 * mPointerXZoomScale;
9999 // When pointers move, the new coordinates equal to the initial coordinates plus
10000 // scaled moving distance.
10001 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
10002 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
10003 0, 0, 0, 0));
10004 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], cookedX2,
10005 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
10006 0, 0, 0, 0));
10007
10008 // Move two fingers down again, expect one MOVE motion event.
10009 y1 += movingDistance;
10010 y2 += movingDistance;
10011
10012 processId(mapper, FIRST_TRACKING_ID);
10013 processPosition(mapper, x1, y1);
10014 processMTSync(mapper);
10015 processId(mapper, SECOND_TRACKING_ID);
10016 processPosition(mapper, x2, y2);
10017 processMTSync(mapper);
10018 processSync(mapper);
10019
10020 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010021 ASSERT_EQ(2U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010022 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010023 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +000010024 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +000010025 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
10026 movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
10027 0, 0, 0, 0, 0));
10028 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], cookedX2,
10029 movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
10030 0, 0, 0, 0, 0));
10031}
10032
Harry Cutts39b7ca22022-10-05 15:55:48 +000010033TEST_F(MultiTouchPointerModeTest, TwoFingerSwipeOffsets) {
Harry Cutts33476232023-01-30 19:57:29 +000010034 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +000010035 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Harry Cutts39b7ca22022-10-05 15:55:48 +000010036 NotifyMotionArgs motionArgs;
10037
10038 // Place two fingers down.
10039 int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125;
10040
10041 processId(mapper, FIRST_TRACKING_ID);
10042 processPosition(mapper, x1, y1);
10043 processMTSync(mapper);
10044 processId(mapper, SECOND_TRACKING_ID);
10045 processPosition(mapper, x2, y2);
10046 processMTSync(mapper);
10047 processSync(mapper);
10048
10049 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010050 ASSERT_EQ(1U, motionArgs.getPointerCount());
Harry Cutts39b7ca22022-10-05 15:55:48 +000010051 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
10052 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
10053 ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET));
10054 ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET));
10055
10056 // Move the two fingers down and to the left.
10057 int32_t movingDistance = 200;
10058 x1 -= movingDistance;
10059 y1 += movingDistance;
10060 x2 -= movingDistance;
10061 y2 += movingDistance;
10062
10063 processId(mapper, FIRST_TRACKING_ID);
10064 processPosition(mapper, x1, y1);
10065 processMTSync(mapper);
10066 processId(mapper, SECOND_TRACKING_ID);
10067 processPosition(mapper, x2, y2);
10068 processMTSync(mapper);
10069 processSync(mapper);
10070
10071 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010072 ASSERT_EQ(1U, motionArgs.getPointerCount());
Harry Cutts39b7ca22022-10-05 15:55:48 +000010073 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
10074 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
10075 ASSERT_LT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET), 0);
10076 ASSERT_GT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET), 0);
10077}
10078
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010079TEST_F(MultiTouchPointerModeTest, WhenViewportActiveStatusChanged_PointerGestureIsReset) {
Harry Cutts33476232023-01-30 19:57:29 +000010080 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010081 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +000010082 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010083 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
10084
10085 // Start a stylus gesture.
10086 processKey(mapper, BTN_TOOL_PEN, 1);
10087 processId(mapper, FIRST_TRACKING_ID);
10088 processPosition(mapper, 100, 200);
10089 processSync(mapper);
10090 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10091 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
10092 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010093 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010094 // TODO(b/257078296): Pointer mode generates extra event.
10095 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10096 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
10097 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010098 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010099 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
10100
10101 // Make the viewport inactive. This will put the device in disabled mode, and the ongoing stylus
10102 // gesture should be disabled.
10103 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
10104 viewport->isActive = false;
10105 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +000010106 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010107 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10108 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
10109 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010110 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010111 // TODO(b/257078296): Pointer mode generates extra event.
10112 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10113 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
10114 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010115 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010116 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
10117}
10118
Arthur Hung6d5b4b22022-01-21 07:21:10 +000010119// --- JoystickInputMapperTest ---
10120
10121class JoystickInputMapperTest : public InputMapperTest {
10122protected:
10123 static const int32_t RAW_X_MIN;
10124 static const int32_t RAW_X_MAX;
10125 static const int32_t RAW_Y_MIN;
10126 static const int32_t RAW_Y_MAX;
10127
10128 void SetUp() override {
10129 InputMapperTest::SetUp(InputDeviceClass::JOYSTICK | InputDeviceClass::EXTERNAL);
10130 }
10131 void prepareAxes() {
10132 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
10133 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
10134 }
10135
10136 void processAxis(JoystickInputMapper& mapper, int32_t axis, int32_t value) {
10137 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, axis, value);
10138 }
10139
10140 void processSync(JoystickInputMapper& mapper) {
10141 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
10142 }
10143
Michael Wrighta9cf4192022-12-01 23:46:39 +000010144 void prepareVirtualDisplay(ui::Rotation orientation) {
Arthur Hung6d5b4b22022-01-21 07:21:10 +000010145 setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH,
10146 VIRTUAL_DISPLAY_HEIGHT, orientation, VIRTUAL_DISPLAY_UNIQUE_ID,
10147 NO_PORT, ViewportType::VIRTUAL);
10148 }
10149};
10150
10151const int32_t JoystickInputMapperTest::RAW_X_MIN = -32767;
10152const int32_t JoystickInputMapperTest::RAW_X_MAX = 32767;
10153const int32_t JoystickInputMapperTest::RAW_Y_MIN = -32767;
10154const int32_t JoystickInputMapperTest::RAW_Y_MAX = 32767;
10155
10156TEST_F(JoystickInputMapperTest, Configure_AssignsDisplayUniqueId) {
10157 prepareAxes();
Arpit Singhae876352023-04-26 14:16:50 +000010158 JoystickInputMapper& mapper = constructAndAddMapper<JoystickInputMapper>();
Arthur Hung6d5b4b22022-01-21 07:21:10 +000010159
10160 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID);
10161
Michael Wrighta9cf4192022-12-01 23:46:39 +000010162 prepareVirtualDisplay(ui::ROTATION_0);
Arthur Hung6d5b4b22022-01-21 07:21:10 +000010163
10164 // Send an axis event
10165 processAxis(mapper, ABS_X, 100);
10166 processSync(mapper);
10167
10168 NotifyMotionArgs args;
10169 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
10170 ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId);
10171
10172 // Send another axis event
10173 processAxis(mapper, ABS_Y, 100);
10174 processSync(mapper);
10175
10176 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
10177 ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId);
10178}
10179
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010180// --- PeripheralControllerTest ---
Chris Yee2b1e5c2021-03-10 22:45:12 -080010181
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010182class PeripheralControllerTest : public testing::Test {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010183protected:
10184 static const char* DEVICE_NAME;
10185 static const char* DEVICE_LOCATION;
10186 static const int32_t DEVICE_ID;
10187 static const int32_t DEVICE_GENERATION;
10188 static const int32_t DEVICE_CONTROLLER_NUMBER;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010189 static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010190 static const int32_t EVENTHUB_ID;
10191
10192 std::shared_ptr<FakeEventHub> mFakeEventHub;
10193 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010194 std::unique_ptr<TestInputListener> mFakeListener;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010195 std::unique_ptr<InstrumentedInputReader> mReader;
10196 std::shared_ptr<InputDevice> mDevice;
10197
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010198 virtual void SetUp(ftl::Flags<InputDeviceClass> classes) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010199 mFakeEventHub = std::make_unique<FakeEventHub>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010200 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010201 mFakeListener = std::make_unique<TestInputListener>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010202 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010203 *mFakeListener);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010204 mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes);
10205 }
10206
10207 void SetUp() override { SetUp(DEVICE_CLASSES); }
10208
10209 void TearDown() override {
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010210 mFakeListener.reset();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010211 mFakePolicy.clear();
10212 }
10213
Chris Yee2b1e5c2021-03-10 22:45:12 -080010214 std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
10215 const std::string& location, int32_t eventHubId,
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010216 ftl::Flags<InputDeviceClass> classes) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010217 InputDeviceIdentifier identifier;
10218 identifier.name = name;
10219 identifier.location = location;
10220 std::shared_ptr<InputDevice> device =
10221 std::make_shared<InputDevice>(mReader->getContext(), deviceId, DEVICE_GENERATION,
10222 identifier);
10223 mReader->pushNextDevice(device);
10224 mFakeEventHub->addDevice(eventHubId, name, classes);
10225 mReader->loopOnce();
10226 return device;
10227 }
10228
10229 template <class T, typename... Args>
10230 T& addControllerAndConfigure(Args... args) {
10231 T& controller = mDevice->addController<T>(EVENTHUB_ID, args...);
10232
10233 return controller;
10234 }
10235};
10236
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010237const char* PeripheralControllerTest::DEVICE_NAME = "device";
10238const char* PeripheralControllerTest::DEVICE_LOCATION = "BLUETOOTH";
10239const int32_t PeripheralControllerTest::DEVICE_ID = END_RESERVED_ID + 1000;
10240const int32_t PeripheralControllerTest::DEVICE_GENERATION = 2;
10241const int32_t PeripheralControllerTest::DEVICE_CONTROLLER_NUMBER = 0;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010242const ftl::Flags<InputDeviceClass> PeripheralControllerTest::DEVICE_CLASSES =
10243 ftl::Flags<InputDeviceClass>(0); // not needed for current tests
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010244const int32_t PeripheralControllerTest::EVENTHUB_ID = 1;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010245
10246// --- BatteryControllerTest ---
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010247class BatteryControllerTest : public PeripheralControllerTest {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010248protected:
10249 void SetUp() override {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010250 PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::BATTERY);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010251 }
10252};
10253
10254TEST_F(BatteryControllerTest, GetBatteryCapacity) {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010255 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010256
Harry Cuttsa5b71292022-11-28 12:56:17 +000010257 ASSERT_TRUE(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY));
10258 ASSERT_EQ(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY).value_or(-1),
10259 FakeEventHub::BATTERY_CAPACITY);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010260}
10261
10262TEST_F(BatteryControllerTest, GetBatteryStatus) {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010263 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010264
Harry Cuttsa5b71292022-11-28 12:56:17 +000010265 ASSERT_TRUE(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY));
10266 ASSERT_EQ(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY).value_or(-1),
10267 FakeEventHub::BATTERY_STATUS);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010268}
10269
10270// --- LightControllerTest ---
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010271class LightControllerTest : public PeripheralControllerTest {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010272protected:
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010273 void SetUp() override {
10274 PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::LIGHT);
10275 }
Chris Yee2b1e5c2021-03-10 22:45:12 -080010276};
10277
Chris Ye85758332021-05-16 23:05:17 -070010278TEST_F(LightControllerTest, MonoLight) {
10279 RawLightInfo infoMono = {.id = 1,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010280 .name = "mono_light",
Chris Ye85758332021-05-16 23:05:17 -070010281 .maxBrightness = 255,
10282 .flags = InputLightClass::BRIGHTNESS,
10283 .path = ""};
10284 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010285
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010286 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010287 InputDeviceInfo info;
10288 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010289 std::vector<InputDeviceLightInfo> lights = info.getLights();
10290 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010291 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10292 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10293
10294 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_BRIGHTNESS));
10295 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_BRIGHTNESS);
10296}
10297
DingYong99f2c3c2023-12-20 15:46:06 +080010298TEST_F(LightControllerTest, MonoKeyboardMuteLight) {
10299 RawLightInfo infoMono = {.id = 1,
10300 .name = "mono_keyboard_mute",
10301 .maxBrightness = 255,
10302 .flags = InputLightClass::BRIGHTNESS |
10303 InputLightClass::KEYBOARD_MIC_MUTE,
10304 .path = ""};
10305 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10306
10307 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10308 std::list<NotifyArgs> unused =
10309 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10310 /*changes=*/{});
10311
10312 InputDeviceInfo info;
10313 controller.populateDeviceInfo(&info);
10314 std::vector<InputDeviceLightInfo> lights = info.getLights();
10315 ASSERT_EQ(1U, lights.size());
10316 ASSERT_EQ(InputDeviceLightType::KEYBOARD_MIC_MUTE, lights[0].type);
10317 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10318}
10319
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010320TEST_F(LightControllerTest, MonoKeyboardBacklight) {
10321 RawLightInfo infoMono = {.id = 1,
10322 .name = "mono_keyboard_backlight",
10323 .maxBrightness = 255,
10324 .flags = InputLightClass::BRIGHTNESS |
10325 InputLightClass::KEYBOARD_BACKLIGHT,
10326 .path = ""};
10327 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10328
10329 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10330 InputDeviceInfo info;
10331 controller.populateDeviceInfo(&info);
10332 std::vector<InputDeviceLightInfo> lights = info.getLights();
10333 ASSERT_EQ(1U, lights.size());
10334 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10335 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010336
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010337 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_BRIGHTNESS));
10338 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_BRIGHTNESS);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010339}
10340
Vaibhav Devmurari16c24192023-05-04 15:20:12 +000010341TEST_F(LightControllerTest, Ignore_MonoLight_WithPreferredBacklightLevels) {
10342 RawLightInfo infoMono = {.id = 1,
10343 .name = "mono_light",
10344 .maxBrightness = 255,
10345 .flags = InputLightClass::BRIGHTNESS,
10346 .path = ""};
10347 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10348 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10349 "0,100,200");
10350
10351 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10352 std::list<NotifyArgs> unused =
10353 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10354 /*changes=*/{});
10355
10356 InputDeviceInfo info;
10357 controller.populateDeviceInfo(&info);
10358 std::vector<InputDeviceLightInfo> lights = info.getLights();
10359 ASSERT_EQ(1U, lights.size());
10360 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10361}
10362
10363TEST_F(LightControllerTest, KeyboardBacklight_WithNoPreferredBacklightLevels) {
10364 RawLightInfo infoMono = {.id = 1,
10365 .name = "mono_keyboard_backlight",
10366 .maxBrightness = 255,
10367 .flags = InputLightClass::BRIGHTNESS |
10368 InputLightClass::KEYBOARD_BACKLIGHT,
10369 .path = ""};
10370 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10371
10372 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10373 std::list<NotifyArgs> unused =
10374 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10375 /*changes=*/{});
10376
10377 InputDeviceInfo info;
10378 controller.populateDeviceInfo(&info);
10379 std::vector<InputDeviceLightInfo> lights = info.getLights();
10380 ASSERT_EQ(1U, lights.size());
10381 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10382}
10383
10384TEST_F(LightControllerTest, KeyboardBacklight_WithPreferredBacklightLevels) {
10385 RawLightInfo infoMono = {.id = 1,
10386 .name = "mono_keyboard_backlight",
10387 .maxBrightness = 255,
10388 .flags = InputLightClass::BRIGHTNESS |
10389 InputLightClass::KEYBOARD_BACKLIGHT,
10390 .path = ""};
10391 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10392 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10393 "0,100,200");
10394
10395 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10396 std::list<NotifyArgs> unused =
10397 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10398 /*changes=*/{});
10399
10400 InputDeviceInfo info;
10401 controller.populateDeviceInfo(&info);
10402 std::vector<InputDeviceLightInfo> lights = info.getLights();
10403 ASSERT_EQ(1U, lights.size());
10404 ASSERT_EQ(3U, lights[0].preferredBrightnessLevels.size());
10405 std::set<BrightnessLevel>::iterator it = lights[0].preferredBrightnessLevels.begin();
10406 ASSERT_EQ(BrightnessLevel(0), *it);
10407 std::advance(it, 1);
10408 ASSERT_EQ(BrightnessLevel(100), *it);
10409 std::advance(it, 1);
10410 ASSERT_EQ(BrightnessLevel(200), *it);
10411}
10412
10413TEST_F(LightControllerTest, KeyboardBacklight_WithWrongPreferredBacklightLevels) {
10414 RawLightInfo infoMono = {.id = 1,
10415 .name = "mono_keyboard_backlight",
10416 .maxBrightness = 255,
10417 .flags = InputLightClass::BRIGHTNESS |
10418 InputLightClass::KEYBOARD_BACKLIGHT,
10419 .path = ""};
10420 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10421 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10422 "0,100,200,300,400,500");
10423
10424 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10425 std::list<NotifyArgs> unused =
10426 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10427 /*changes=*/{});
10428
10429 InputDeviceInfo info;
10430 controller.populateDeviceInfo(&info);
10431 std::vector<InputDeviceLightInfo> lights = info.getLights();
10432 ASSERT_EQ(1U, lights.size());
10433 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10434}
10435
Chris Yee2b1e5c2021-03-10 22:45:12 -080010436TEST_F(LightControllerTest, RGBLight) {
10437 RawLightInfo infoRed = {.id = 1,
10438 .name = "red",
10439 .maxBrightness = 255,
10440 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED,
10441 .path = ""};
10442 RawLightInfo infoGreen = {.id = 2,
10443 .name = "green",
10444 .maxBrightness = 255,
10445 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN,
10446 .path = ""};
10447 RawLightInfo infoBlue = {.id = 3,
10448 .name = "blue",
10449 .maxBrightness = 255,
10450 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE,
10451 .path = ""};
10452 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10453 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10454 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10455
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010456 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010457 InputDeviceInfo info;
10458 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010459 std::vector<InputDeviceLightInfo> lights = info.getLights();
10460 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010461 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10462 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10463 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10464
10465 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10466 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10467}
10468
10469TEST_F(LightControllerTest, CorrectRGBKeyboardBacklight) {
10470 RawLightInfo infoRed = {.id = 1,
10471 .name = "red_keyboard_backlight",
10472 .maxBrightness = 255,
10473 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED |
10474 InputLightClass::KEYBOARD_BACKLIGHT,
10475 .path = ""};
10476 RawLightInfo infoGreen = {.id = 2,
10477 .name = "green_keyboard_backlight",
10478 .maxBrightness = 255,
10479 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN |
10480 InputLightClass::KEYBOARD_BACKLIGHT,
10481 .path = ""};
10482 RawLightInfo infoBlue = {.id = 3,
10483 .name = "blue_keyboard_backlight",
10484 .maxBrightness = 255,
10485 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE |
10486 InputLightClass::KEYBOARD_BACKLIGHT,
10487 .path = ""};
10488 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10489 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10490 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10491
10492 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10493 InputDeviceInfo info;
10494 controller.populateDeviceInfo(&info);
10495 std::vector<InputDeviceLightInfo> lights = info.getLights();
10496 ASSERT_EQ(1U, lights.size());
10497 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10498 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10499 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10500
10501 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10502 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10503}
10504
10505TEST_F(LightControllerTest, IncorrectRGBKeyboardBacklight) {
10506 RawLightInfo infoRed = {.id = 1,
10507 .name = "red",
10508 .maxBrightness = 255,
10509 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED,
10510 .path = ""};
10511 RawLightInfo infoGreen = {.id = 2,
10512 .name = "green",
10513 .maxBrightness = 255,
10514 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN,
10515 .path = ""};
10516 RawLightInfo infoBlue = {.id = 3,
10517 .name = "blue",
10518 .maxBrightness = 255,
10519 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE,
10520 .path = ""};
10521 RawLightInfo infoGlobal = {.id = 3,
10522 .name = "global_keyboard_backlight",
10523 .maxBrightness = 255,
10524 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GLOBAL |
10525 InputLightClass::KEYBOARD_BACKLIGHT,
10526 .path = ""};
10527 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10528 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10529 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10530 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoGlobal));
10531
10532 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10533 InputDeviceInfo info;
10534 controller.populateDeviceInfo(&info);
10535 std::vector<InputDeviceLightInfo> lights = info.getLights();
10536 ASSERT_EQ(1U, lights.size());
10537 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10538 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10539 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010540
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010541 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10542 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010543}
10544
10545TEST_F(LightControllerTest, MultiColorRGBLight) {
10546 RawLightInfo infoColor = {.id = 1,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010547 .name = "multi_color",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010548 .maxBrightness = 255,
10549 .flags = InputLightClass::BRIGHTNESS |
10550 InputLightClass::MULTI_INTENSITY |
10551 InputLightClass::MULTI_INDEX,
10552 .path = ""};
10553
10554 mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
10555
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010556 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010557 InputDeviceInfo info;
10558 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010559 std::vector<InputDeviceLightInfo> lights = info.getLights();
10560 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010561 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10562 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10563 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10564
10565 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10566 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10567}
10568
10569TEST_F(LightControllerTest, MultiColorRGBKeyboardBacklight) {
10570 RawLightInfo infoColor = {.id = 1,
10571 .name = "multi_color_keyboard_backlight",
10572 .maxBrightness = 255,
10573 .flags = InputLightClass::BRIGHTNESS |
10574 InputLightClass::MULTI_INTENSITY |
10575 InputLightClass::MULTI_INDEX |
10576 InputLightClass::KEYBOARD_BACKLIGHT,
10577 .path = ""};
10578
10579 mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
10580
10581 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10582 InputDeviceInfo info;
10583 controller.populateDeviceInfo(&info);
10584 std::vector<InputDeviceLightInfo> lights = info.getLights();
10585 ASSERT_EQ(1U, lights.size());
10586 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10587 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10588 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010589
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010590 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10591 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010592}
10593
Josep del Rioa1046a82023-08-24 19:57:27 +000010594TEST_F(LightControllerTest, SonyPlayerIdLight) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010595 RawLightInfo info1 = {.id = 1,
Josep del Rioa1046a82023-08-24 19:57:27 +000010596 .name = "sony1",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010597 .maxBrightness = 255,
10598 .flags = InputLightClass::BRIGHTNESS,
10599 .path = ""};
10600 RawLightInfo info2 = {.id = 2,
Josep del Rioa1046a82023-08-24 19:57:27 +000010601 .name = "sony2",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010602 .maxBrightness = 255,
10603 .flags = InputLightClass::BRIGHTNESS,
10604 .path = ""};
10605 RawLightInfo info3 = {.id = 3,
Josep del Rioa1046a82023-08-24 19:57:27 +000010606 .name = "sony3",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010607 .maxBrightness = 255,
10608 .flags = InputLightClass::BRIGHTNESS,
10609 .path = ""};
10610 RawLightInfo info4 = {.id = 4,
Josep del Rioa1046a82023-08-24 19:57:27 +000010611 .name = "sony4",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010612 .maxBrightness = 255,
10613 .flags = InputLightClass::BRIGHTNESS,
10614 .path = ""};
10615 mFakeEventHub->addRawLightInfo(info1.id, std::move(info1));
10616 mFakeEventHub->addRawLightInfo(info2.id, std::move(info2));
10617 mFakeEventHub->addRawLightInfo(info3.id, std::move(info3));
10618 mFakeEventHub->addRawLightInfo(info4.id, std::move(info4));
10619
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010620 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010621 InputDeviceInfo info;
10622 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010623 std::vector<InputDeviceLightInfo> lights = info.getLights();
10624 ASSERT_EQ(1U, lights.size());
Josep del Rioa1046a82023-08-24 19:57:27 +000010625 ASSERT_STREQ("sony", lights[0].name.c_str());
10626 ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
10627 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10628 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10629
10630 ASSERT_FALSE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10631 ASSERT_TRUE(controller.setLightPlayerId(lights[0].id, LIGHT_PLAYER_ID));
10632 ASSERT_EQ(controller.getLightPlayerId(lights[0].id).value_or(-1), LIGHT_PLAYER_ID);
10633 ASSERT_STREQ("sony", lights[0].name.c_str());
10634}
10635
10636TEST_F(LightControllerTest, PlayerIdLight) {
10637 RawLightInfo info1 = {.id = 1,
10638 .name = "player-1",
10639 .maxBrightness = 255,
10640 .flags = InputLightClass::BRIGHTNESS,
10641 .path = ""};
10642 RawLightInfo info2 = {.id = 2,
10643 .name = "player-2",
10644 .maxBrightness = 255,
10645 .flags = InputLightClass::BRIGHTNESS,
10646 .path = ""};
10647 RawLightInfo info3 = {.id = 3,
10648 .name = "player-3",
10649 .maxBrightness = 255,
10650 .flags = InputLightClass::BRIGHTNESS,
10651 .path = ""};
10652 RawLightInfo info4 = {.id = 4,
10653 .name = "player-4",
10654 .maxBrightness = 255,
10655 .flags = InputLightClass::BRIGHTNESS,
10656 .path = ""};
10657 mFakeEventHub->addRawLightInfo(info1.id, std::move(info1));
10658 mFakeEventHub->addRawLightInfo(info2.id, std::move(info2));
10659 mFakeEventHub->addRawLightInfo(info3.id, std::move(info3));
10660 mFakeEventHub->addRawLightInfo(info4.id, std::move(info4));
10661
10662 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10663 InputDeviceInfo info;
10664 controller.populateDeviceInfo(&info);
10665 std::vector<InputDeviceLightInfo> lights = info.getLights();
10666 ASSERT_EQ(1U, lights.size());
10667 ASSERT_STREQ("player", lights[0].name.c_str());
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010668 ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010669 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10670 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010671
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010672 ASSERT_FALSE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10673 ASSERT_TRUE(controller.setLightPlayerId(lights[0].id, LIGHT_PLAYER_ID));
10674 ASSERT_EQ(controller.getLightPlayerId(lights[0].id).value_or(-1), LIGHT_PLAYER_ID);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010675}
10676
Michael Wrightd02c5b62014-02-10 15:10:22 -080010677} // namespace android