blob: 33ba79e71736a843cb9efbd1b8291e9096164777 [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>
Chris Ye1dd2e5c2021-04-04 23:12:41 -070030#include <PeripheralController.h>
Chris Yef59a2f42020-10-16 12:55:26 -070031#include <SensorInputMapper.h>
Prabir Pradhan2770d242019-09-02 18:07:11 -070032#include <SingleTouchInputMapper.h>
33#include <SwitchInputMapper.h>
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000034#include <TestEventMatchers.h>
Prabir Pradhan2770d242019-09-02 18:07:11 -070035#include <TestInputListener.h>
36#include <TouchInputMapper.h>
Prabir Pradhan1aed8582019-12-30 11:46:51 -080037#include <UinputDevice.h>
Chris Ye87143712020-11-10 05:05:58 +000038#include <VibratorInputMapper.h>
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070039#include <android-base/thread_annotations.h>
Byoungho Jungda10dd32023-10-06 17:03:45 +090040#include <com_android_input_flags.h>
Michael Wrighta9cf4192022-12-01 23:46:39 +000041#include <ftl/enum.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080042#include <gtest/gtest.h>
chaviw3277faf2021-05-19 16:45:23 -050043#include <gui/constants.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 Cuttsb57f1702022-11-28 15:34:22 +000049#include "FakePointerController.h"
Harry Cuttse6512e12022-11-28 18:44:01 +000050#include "InputMapperTest.h"
Harry Cutts144ff542022-11-28 17:41:06 +000051#include "InstrumentedInputReader.h"
Harry Cuttsa5b71292022-11-28 12:56:17 +000052#include "TestConstants.h"
Michael Wrightdde67b82020-10-27 16:09:22 +000053#include "input/DisplayViewport.h"
54#include "input/Input.h"
Michael Wright17db18e2020-06-26 20:51:44 +010055
Michael Wrightd02c5b62014-02-10 15:10:22 -080056namespace android {
57
Dominik Laskowski2f01d772022-03-23 16:01:29 -070058using namespace ftl::flag_operators;
Prabir Pradhan739dca42022-09-09 20:12:01 +000059using testing::AllOf;
Biswarup Palb08159b2024-08-22 09:12:19 +000060using testing::VariantWith;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070061using std::chrono_literals::operator""ms;
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -080062using std::chrono_literals::operator""s;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070063
Michael Wrightd02c5b62014-02-10 15:10:22 -080064// Arbitrary display properties.
arthurhungcc7f9802020-04-30 17:55:40 +080065static constexpr int32_t DISPLAY_ID = 0;
Prabir Pradhanc13ff082022-09-08 22:03:30 +000066static const std::string DISPLAY_UNIQUE_ID = "local:1";
arthurhungcc7f9802020-04-30 17:55:40 +080067static constexpr int32_t SECONDARY_DISPLAY_ID = DISPLAY_ID + 1;
Prabir Pradhanc13ff082022-09-08 22:03:30 +000068static const std::string SECONDARY_DISPLAY_UNIQUE_ID = "local:2";
arthurhungcc7f9802020-04-30 17:55:40 +080069static constexpr int32_t DISPLAY_WIDTH = 480;
70static constexpr int32_t DISPLAY_HEIGHT = 800;
71static constexpr int32_t VIRTUAL_DISPLAY_ID = 1;
72static constexpr int32_t VIRTUAL_DISPLAY_WIDTH = 400;
73static constexpr int32_t VIRTUAL_DISPLAY_HEIGHT = 500;
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -070074static const char* VIRTUAL_DISPLAY_UNIQUE_ID = "virtual:1";
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -070075static constexpr std::optional<uint8_t> NO_PORT = std::nullopt; // no physical port is specified
Michael Wrightd02c5b62014-02-10 15:10:22 -080076
arthurhungcc7f9802020-04-30 17:55:40 +080077static constexpr int32_t FIRST_SLOT = 0;
78static constexpr int32_t SECOND_SLOT = 1;
79static constexpr int32_t THIRD_SLOT = 2;
80static constexpr int32_t INVALID_TRACKING_ID = -1;
81static constexpr int32_t FIRST_TRACKING_ID = 0;
82static constexpr int32_t SECOND_TRACKING_ID = 1;
83static constexpr int32_t THIRD_TRACKING_ID = 2;
Chris Ye3fdbfef2021-01-06 18:45:18 -080084static constexpr int32_t LIGHT_BRIGHTNESS = 0x55000000;
85static constexpr int32_t LIGHT_COLOR = 0x7F448866;
86static constexpr int32_t LIGHT_PLAYER_ID = 2;
arthurhungcc7f9802020-04-30 17:55:40 +080087
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -080088static constexpr int32_t ACTION_POINTER_0_DOWN =
89 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
90static constexpr int32_t ACTION_POINTER_0_UP =
91 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
92static constexpr int32_t ACTION_POINTER_1_DOWN =
93 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
94static constexpr int32_t ACTION_POINTER_1_UP =
95 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
96
Prabir Pradhanb08a0e82023-09-14 22:28:32 +000097static constexpr uint32_t STYLUS_FUSION_SOURCE =
98 AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_BLUETOOTH_STYLUS;
99
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +0000100// Minimum timestamp separation between subsequent input events from a Bluetooth device.
101static constexpr nsecs_t MIN_BLUETOOTH_TIMESTAMP_DELTA = ms2ns(4);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +0000102
Byoungho Jungda10dd32023-10-06 17:03:45 +0900103namespace input_flags = com::android::input::flags;
104
Michael Wrightd02c5b62014-02-10 15:10:22 -0800105template<typename T>
106static inline T min(T a, T b) {
107 return a < b ? a : b;
108}
109
110static inline float avg(float x, float y) {
111 return (x + y) / 2;
112}
113
Chris Ye3fdbfef2021-01-06 18:45:18 -0800114// Mapping for light color name and the light color
115const std::unordered_map<std::string, LightColor> LIGHT_COLORS = {{"red", LightColor::RED},
116 {"green", LightColor::GREEN},
117 {"blue", LightColor::BLUE}};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800118
Michael Wrighta9cf4192022-12-01 23:46:39 +0000119static ui::Rotation getInverseRotation(ui::Rotation orientation) {
Prabir Pradhanc14266f2021-05-12 15:56:24 -0700120 switch (orientation) {
Michael Wrighta9cf4192022-12-01 23:46:39 +0000121 case ui::ROTATION_90:
122 return ui::ROTATION_270;
123 case ui::ROTATION_270:
124 return ui::ROTATION_90;
Prabir Pradhanc14266f2021-05-12 15:56:24 -0700125 default:
126 return orientation;
127 }
128}
129
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800130static void assertAxisResolution(MultiTouchInputMapper& mapper, int axis, float resolution) {
131 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +0000132 mapper.populateDeviceInfo(info);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800133
134 const InputDeviceInfo::MotionRange* motionRange =
135 info.getMotionRange(axis, AINPUT_SOURCE_TOUCHSCREEN);
136 ASSERT_NEAR(motionRange->resolution, resolution, EPSILON);
137}
138
139static void assertAxisNotPresent(MultiTouchInputMapper& mapper, int axis) {
140 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +0000141 mapper.populateDeviceInfo(info);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800142
143 const InputDeviceInfo::MotionRange* motionRange =
144 info.getMotionRange(axis, AINPUT_SOURCE_TOUCHSCREEN);
145 ASSERT_EQ(nullptr, motionRange);
146}
147
Siarhei Vishniakou21e96e62022-10-27 10:23:37 -0700148[[maybe_unused]] static void dumpReader(InputReader& reader) {
149 std::string dump;
150 reader.dump(dump);
151 std::istringstream iss(dump);
152 for (std::string line; std::getline(iss, line);) {
153 ALOGE("%s", line.c_str());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -0800154 std::this_thread::sleep_for(1ms);
Siarhei Vishniakou21e96e62022-10-27 10:23:37 -0700155 }
156}
157
Michael Wrightd02c5b62014-02-10 15:10:22 -0800158// --- FakeInputMapper ---
159
160class FakeInputMapper : public InputMapper {
161 uint32_t mSources;
162 int32_t mKeyboardType;
163 int32_t mMetaState;
164 KeyedVector<int32_t, int32_t> mKeyCodeStates;
165 KeyedVector<int32_t, int32_t> mScanCodeStates;
166 KeyedVector<int32_t, int32_t> mSwitchStates;
Philip Junker4af3b3d2021-12-14 10:36:55 +0100167 // fake mapping which would normally come from keyCharacterMap
168 std::unordered_map<int32_t, int32_t> mKeyCodeMapping;
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800169 std::vector<int32_t> mSupportedKeyCodes;
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700170 std::list<NotifyArgs> mProcessResult;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800171
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700172 std::mutex mLock;
173 std::condition_variable mStateChangedCondition;
174 bool mConfigureWasCalled GUARDED_BY(mLock);
175 bool mResetWasCalled GUARDED_BY(mLock);
176 bool mProcessWasCalled GUARDED_BY(mLock);
177 RawEvent mLastEvent GUARDED_BY(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800178
Arthur Hungc23540e2018-11-29 20:42:11 +0800179 std::optional<DisplayViewport> mViewport;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800180public:
Arpit Singh8e6fb252023-04-06 11:49:17 +0000181 FakeInputMapper(InputDeviceContext& deviceContext, const InputReaderConfiguration& readerConfig,
182 uint32_t sources)
183 : InputMapper(deviceContext, readerConfig),
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800184 mSources(sources),
185 mKeyboardType(AINPUT_KEYBOARD_TYPE_NONE),
Michael Wrightd02c5b62014-02-10 15:10:22 -0800186 mMetaState(0),
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800187 mConfigureWasCalled(false),
188 mResetWasCalled(false),
189 mProcessWasCalled(false) {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800190
Chris Yea52ade12020-08-27 16:49:20 -0700191 virtual ~FakeInputMapper() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800192
193 void setKeyboardType(int32_t keyboardType) {
194 mKeyboardType = keyboardType;
195 }
196
197 void setMetaState(int32_t metaState) {
198 mMetaState = metaState;
199 }
200
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700201 // Sets the return value for the `process` call.
202 void setProcessResult(std::list<NotifyArgs> notifyArgs) {
203 mProcessResult.clear();
204 for (auto notifyArg : notifyArgs) {
205 mProcessResult.push_back(notifyArg);
206 }
207 }
208
Michael Wrightd02c5b62014-02-10 15:10:22 -0800209 void assertConfigureWasCalled() {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700210 std::unique_lock<std::mutex> lock(mLock);
211 base::ScopedLockAssertion assumeLocked(mLock);
212 const bool configureCalled =
213 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
214 return mConfigureWasCalled;
215 });
216 if (!configureCalled) {
217 FAIL() << "Expected configure() to have been called.";
218 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800219 mConfigureWasCalled = false;
220 }
221
222 void assertResetWasCalled() {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700223 std::unique_lock<std::mutex> lock(mLock);
224 base::ScopedLockAssertion assumeLocked(mLock);
225 const bool resetCalled =
226 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
227 return mResetWasCalled;
228 });
229 if (!resetCalled) {
230 FAIL() << "Expected reset() to have been called.";
231 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800232 mResetWasCalled = false;
233 }
234
Prabir Pradhanf8d9e442023-12-06 22:06:13 +0000235 void assertResetWasNotCalled() {
236 std::scoped_lock lock(mLock);
237 ASSERT_FALSE(mResetWasCalled) << "Expected reset to not have been called.";
238 }
239
Yi Kong9b14ac62018-07-17 13:48:38 -0700240 void assertProcessWasCalled(RawEvent* outLastEvent = nullptr) {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700241 std::unique_lock<std::mutex> lock(mLock);
242 base::ScopedLockAssertion assumeLocked(mLock);
243 const bool processCalled =
244 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
245 return mProcessWasCalled;
246 });
247 if (!processCalled) {
248 FAIL() << "Expected process() to have been called.";
249 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800250 if (outLastEvent) {
251 *outLastEvent = mLastEvent;
252 }
253 mProcessWasCalled = false;
254 }
255
Prabir Pradhanf8d9e442023-12-06 22:06:13 +0000256 void assertProcessWasNotCalled() {
257 std::scoped_lock lock(mLock);
258 ASSERT_FALSE(mProcessWasCalled) << "Expected process to not have been called.";
259 }
260
Michael Wrightd02c5b62014-02-10 15:10:22 -0800261 void setKeyCodeState(int32_t keyCode, int32_t state) {
262 mKeyCodeStates.replaceValueFor(keyCode, state);
263 }
264
265 void setScanCodeState(int32_t scanCode, int32_t state) {
266 mScanCodeStates.replaceValueFor(scanCode, state);
267 }
268
269 void setSwitchState(int32_t switchCode, int32_t state) {
270 mSwitchStates.replaceValueFor(switchCode, state);
271 }
272
273 void addSupportedKeyCode(int32_t keyCode) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800274 mSupportedKeyCodes.push_back(keyCode);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800275 }
276
Philip Junker4af3b3d2021-12-14 10:36:55 +0100277 void addKeyCodeMapping(int32_t fromKeyCode, int32_t toKeyCode) {
278 mKeyCodeMapping.insert_or_assign(fromKeyCode, toKeyCode);
279 }
280
Michael Wrightd02c5b62014-02-10 15:10:22 -0800281private:
Philip Junker4af3b3d2021-12-14 10:36:55 +0100282 uint32_t getSources() const override { return mSources; }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800283
Harry Cuttsd02ea102023-03-17 18:21:30 +0000284 void populateDeviceInfo(InputDeviceInfo& deviceInfo) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800285 InputMapper::populateDeviceInfo(deviceInfo);
286
287 if (mKeyboardType != AINPUT_KEYBOARD_TYPE_NONE) {
Harry Cuttsd02ea102023-03-17 18:21:30 +0000288 deviceInfo.setKeyboardType(mKeyboardType);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800289 }
290 }
291
Arpit Singhed6c3de2023-04-05 19:24:37 +0000292 std::list<NotifyArgs> reconfigure(nsecs_t, const InputReaderConfiguration& config,
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000293 ConfigurationChanges changes) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700294 std::scoped_lock<std::mutex> lock(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800295 mConfigureWasCalled = true;
Arthur Hungc23540e2018-11-29 20:42:11 +0800296
297 // Find the associated viewport if exist.
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800298 const std::optional<uint8_t> displayPort = getDeviceContext().getAssociatedDisplayPort();
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000299 if (displayPort && changes.test(InputReaderConfiguration::Change::DISPLAY_INFO)) {
Arpit Singhed6c3de2023-04-05 19:24:37 +0000300 mViewport = config.getDisplayViewportByPort(*displayPort);
Arthur Hungc23540e2018-11-29 20:42:11 +0800301 }
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700302
303 mStateChangedCondition.notify_all();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700304 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800305 }
306
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700307 std::list<NotifyArgs> reset(nsecs_t) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700308 std::scoped_lock<std::mutex> lock(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800309 mResetWasCalled = true;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700310 mStateChangedCondition.notify_all();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700311 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800312 }
313
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700314 std::list<NotifyArgs> process(const RawEvent* rawEvent) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700315 std::scoped_lock<std::mutex> lock(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800316 mLastEvent = *rawEvent;
317 mProcessWasCalled = true;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700318 mStateChangedCondition.notify_all();
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700319 return mProcessResult;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800320 }
321
Chris Yea52ade12020-08-27 16:49:20 -0700322 int32_t getKeyCodeState(uint32_t, int32_t keyCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800323 ssize_t index = mKeyCodeStates.indexOfKey(keyCode);
324 return index >= 0 ? mKeyCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
325 }
326
Philip Junker4af3b3d2021-12-14 10:36:55 +0100327 int32_t getKeyCodeForKeyLocation(int32_t locationKeyCode) const override {
328 auto it = mKeyCodeMapping.find(locationKeyCode);
329 return it != mKeyCodeMapping.end() ? it->second : locationKeyCode;
330 }
331
Chris Yea52ade12020-08-27 16:49:20 -0700332 int32_t getScanCodeState(uint32_t, int32_t scanCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800333 ssize_t index = mScanCodeStates.indexOfKey(scanCode);
334 return index >= 0 ? mScanCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
335 }
336
Chris Yea52ade12020-08-27 16:49:20 -0700337 int32_t getSwitchState(uint32_t, int32_t switchCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800338 ssize_t index = mSwitchStates.indexOfKey(switchCode);
339 return index >= 0 ? mSwitchStates.valueAt(index) : AKEY_STATE_UNKNOWN;
340 }
341
Chris Yea52ade12020-08-27 16:49:20 -0700342 // Return true if the device has non-empty key layout.
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700343 bool markSupportedKeyCodes(uint32_t, const std::vector<int32_t>& keyCodes,
Chris Yea52ade12020-08-27 16:49:20 -0700344 uint8_t* outFlags) override {
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700345 for (size_t i = 0; i < keyCodes.size(); i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800346 for (size_t j = 0; j < mSupportedKeyCodes.size(); j++) {
347 if (keyCodes[i] == mSupportedKeyCodes[j]) {
348 outFlags[i] = 1;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800349 }
350 }
351 }
Chris Yea52ade12020-08-27 16:49:20 -0700352 bool result = mSupportedKeyCodes.size() > 0;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800353 return result;
354 }
355
356 virtual int32_t getMetaState() {
357 return mMetaState;
358 }
359
360 virtual void fadePointer() {
361 }
Arthur Hungc23540e2018-11-29 20:42:11 +0800362
363 virtual std::optional<int32_t> getAssociatedDisplay() {
364 if (mViewport) {
365 return std::make_optional(mViewport->displayId);
366 }
367 return std::nullopt;
368 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800369};
370
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700371// --- InputReaderPolicyTest ---
372class InputReaderPolicyTest : public testing::Test {
Siarhei Vishniakoucd7ac1e2018-10-15 13:39:50 -0700373protected:
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700374 sp<FakeInputReaderPolicy> mFakePolicy;
375
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700376 void SetUp() override { mFakePolicy = sp<FakeInputReaderPolicy>::make(); }
Chris Yea52ade12020-08-27 16:49:20 -0700377 void TearDown() override { mFakePolicy.clear(); }
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700378};
379
380/**
381 * Check that empty set of viewports is an acceptable configuration.
382 * Also try to get internal viewport two different ways - by type and by uniqueId.
383 *
384 * There will be confusion if two viewports with empty uniqueId and identical type are present.
385 * Such configuration is not currently allowed.
386 */
387TEST_F(InputReaderPolicyTest, Viewports_GetCleared) {
Siarhei Vishniakoucd7ac1e2018-10-15 13:39:50 -0700388 static const std::string uniqueId = "local:0";
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700389
390 // We didn't add any viewports yet, so there shouldn't be any.
391 std::optional<DisplayViewport> internalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100392 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700393 ASSERT_FALSE(internalViewport);
394
395 // Add an internal viewport, then clear it
Michael Wrighta9cf4192022-12-01 23:46:39 +0000396 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000397 /*isActive=*/true, uniqueId, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700398
399 // Check matching by uniqueId
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700400 internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700401 ASSERT_TRUE(internalViewport);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100402 ASSERT_EQ(ViewportType::INTERNAL, internalViewport->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700403
404 // Check matching by viewport type
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100405 internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700406 ASSERT_TRUE(internalViewport);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700407 ASSERT_EQ(uniqueId, internalViewport->uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700408
409 mFakePolicy->clearViewports();
410 // Make sure nothing is found after clear
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700411 internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700412 ASSERT_FALSE(internalViewport);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100413 internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700414 ASSERT_FALSE(internalViewport);
415}
416
417TEST_F(InputReaderPolicyTest, Viewports_GetByType) {
418 const std::string internalUniqueId = "local:0";
419 const std::string externalUniqueId = "local:1";
420 const std::string virtualUniqueId1 = "virtual:2";
421 const std::string virtualUniqueId2 = "virtual:3";
422 constexpr int32_t virtualDisplayId1 = 2;
423 constexpr int32_t virtualDisplayId2 = 3;
424
425 // Add an internal viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000426 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000427 /*isActive=*/true, internalUniqueId, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000428 ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700429 // Add an external viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000430 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000431 /*isActive=*/true, externalUniqueId, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000432 ViewportType::EXTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700433 // Add an virtual viewport
434 mFakePolicy->addDisplayViewport(virtualDisplayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000435 ui::ROTATION_0, /*isActive=*/true, virtualUniqueId1, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000436 ViewportType::VIRTUAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700437 // Add another virtual viewport
438 mFakePolicy->addDisplayViewport(virtualDisplayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000439 ui::ROTATION_0, /*isActive=*/true, virtualUniqueId2, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000440 ViewportType::VIRTUAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700441
442 // Check matching by type for internal
443 std::optional<DisplayViewport> internalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100444 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700445 ASSERT_TRUE(internalViewport);
446 ASSERT_EQ(internalUniqueId, internalViewport->uniqueId);
447
448 // Check matching by type for external
449 std::optional<DisplayViewport> externalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100450 mFakePolicy->getDisplayViewportByType(ViewportType::EXTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700451 ASSERT_TRUE(externalViewport);
452 ASSERT_EQ(externalUniqueId, externalViewport->uniqueId);
453
454 // Check matching by uniqueId for virtual viewport #1
455 std::optional<DisplayViewport> virtualViewport1 =
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700456 mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId1);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700457 ASSERT_TRUE(virtualViewport1);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100458 ASSERT_EQ(ViewportType::VIRTUAL, virtualViewport1->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700459 ASSERT_EQ(virtualUniqueId1, virtualViewport1->uniqueId);
460 ASSERT_EQ(virtualDisplayId1, virtualViewport1->displayId);
461
462 // Check matching by uniqueId for virtual viewport #2
463 std::optional<DisplayViewport> virtualViewport2 =
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700464 mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId2);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700465 ASSERT_TRUE(virtualViewport2);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100466 ASSERT_EQ(ViewportType::VIRTUAL, virtualViewport2->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700467 ASSERT_EQ(virtualUniqueId2, virtualViewport2->uniqueId);
468 ASSERT_EQ(virtualDisplayId2, virtualViewport2->displayId);
469}
470
471
472/**
473 * We can have 2 viewports of the same kind. We can distinguish them by uniqueId, and confirm
474 * that lookup works by checking display id.
475 * Check that 2 viewports of each kind is possible, for all existing viewport types.
476 */
477TEST_F(InputReaderPolicyTest, Viewports_TwoOfSameType) {
478 const std::string uniqueId1 = "uniqueId1";
479 const std::string uniqueId2 = "uniqueId2";
480 constexpr int32_t displayId1 = 2;
481 constexpr int32_t displayId2 = 3;
482
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100483 std::vector<ViewportType> types = {ViewportType::INTERNAL, ViewportType::EXTERNAL,
484 ViewportType::VIRTUAL};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700485 for (const ViewportType& type : types) {
486 mFakePolicy->clearViewports();
487 // Add a viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000488 mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000489 /*isActive=*/true, uniqueId1, NO_PORT, type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700490 // Add another viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000491 mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000492 /*isActive=*/true, uniqueId2, NO_PORT, type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700493
494 // Check that correct display viewport was returned by comparing the display IDs.
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700495 std::optional<DisplayViewport> viewport1 =
496 mFakePolicy->getDisplayViewportByUniqueId(uniqueId1);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700497 ASSERT_TRUE(viewport1);
498 ASSERT_EQ(displayId1, viewport1->displayId);
499 ASSERT_EQ(type, viewport1->type);
500
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700501 std::optional<DisplayViewport> viewport2 =
502 mFakePolicy->getDisplayViewportByUniqueId(uniqueId2);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700503 ASSERT_TRUE(viewport2);
504 ASSERT_EQ(displayId2, viewport2->displayId);
505 ASSERT_EQ(type, viewport2->type);
506
507 // When there are multiple viewports of the same kind, and uniqueId is not specified
508 // in the call to getDisplayViewport, then that situation is not supported.
509 // The viewports can be stored in any order, so we cannot rely on the order, since that
510 // is just implementation detail.
511 // However, we can check that it still returns *a* viewport, we just cannot assert
512 // which one specifically is returned.
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700513 std::optional<DisplayViewport> someViewport = mFakePolicy->getDisplayViewportByType(type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700514 ASSERT_TRUE(someViewport);
515 }
516}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800517
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700518/**
Michael Wrightdde67b82020-10-27 16:09:22 +0000519 * When we have multiple internal displays make sure we always return the default display when
520 * querying by type.
521 */
522TEST_F(InputReaderPolicyTest, Viewports_ByTypeReturnsDefaultForInternal) {
523 const std::string uniqueId1 = "uniqueId1";
524 const std::string uniqueId2 = "uniqueId2";
525 constexpr int32_t nonDefaultDisplayId = 2;
526 static_assert(nonDefaultDisplayId != ADISPLAY_ID_DEFAULT,
527 "Test display ID should not be ADISPLAY_ID_DEFAULT");
528
529 // Add the default display first and ensure it gets returned.
530 mFakePolicy->clearViewports();
531 mFakePolicy->addDisplayViewport(ADISPLAY_ID_DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000532 ui::ROTATION_0, /*isActive=*/true, uniqueId1, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000533 ViewportType::INTERNAL);
534 mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000535 ui::ROTATION_0, /*isActive=*/true, uniqueId2, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000536 ViewportType::INTERNAL);
537
538 std::optional<DisplayViewport> viewport =
539 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
540 ASSERT_TRUE(viewport);
541 ASSERT_EQ(ADISPLAY_ID_DEFAULT, viewport->displayId);
542 ASSERT_EQ(ViewportType::INTERNAL, viewport->type);
543
544 // Add the default display second to make sure order doesn't matter.
545 mFakePolicy->clearViewports();
546 mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000547 ui::ROTATION_0, /*isActive=*/true, uniqueId2, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000548 ViewportType::INTERNAL);
549 mFakePolicy->addDisplayViewport(ADISPLAY_ID_DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000550 ui::ROTATION_0, /*isActive=*/true, uniqueId1, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000551 ViewportType::INTERNAL);
552
553 viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
554 ASSERT_TRUE(viewport);
555 ASSERT_EQ(ADISPLAY_ID_DEFAULT, viewport->displayId);
556 ASSERT_EQ(ViewportType::INTERNAL, viewport->type);
557}
558
559/**
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700560 * Check getDisplayViewportByPort
561 */
562TEST_F(InputReaderPolicyTest, Viewports_GetByPort) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100563 constexpr ViewportType type = ViewportType::EXTERNAL;
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700564 const std::string uniqueId1 = "uniqueId1";
565 const std::string uniqueId2 = "uniqueId2";
566 constexpr int32_t displayId1 = 1;
567 constexpr int32_t displayId2 = 2;
568 const uint8_t hdmi1 = 0;
569 const uint8_t hdmi2 = 1;
570 const uint8_t hdmi3 = 2;
571
572 mFakePolicy->clearViewports();
573 // Add a viewport that's associated with some display port that's not of interest.
Michael Wrighta9cf4192022-12-01 23:46:39 +0000574 mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000575 /*isActive=*/true, uniqueId1, hdmi3, type);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700576 // Add another viewport, connected to HDMI1 port
Michael Wrighta9cf4192022-12-01 23:46:39 +0000577 mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000578 /*isActive=*/true, uniqueId2, hdmi1, type);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700579
580 // Check that correct display viewport was returned by comparing the display ports.
581 std::optional<DisplayViewport> hdmi1Viewport = mFakePolicy->getDisplayViewportByPort(hdmi1);
582 ASSERT_TRUE(hdmi1Viewport);
583 ASSERT_EQ(displayId2, hdmi1Viewport->displayId);
584 ASSERT_EQ(uniqueId2, hdmi1Viewport->uniqueId);
585
586 // Check that we can still get the same viewport using the uniqueId
587 hdmi1Viewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId2);
588 ASSERT_TRUE(hdmi1Viewport);
589 ASSERT_EQ(displayId2, hdmi1Viewport->displayId);
590 ASSERT_EQ(uniqueId2, hdmi1Viewport->uniqueId);
591 ASSERT_EQ(type, hdmi1Viewport->type);
592
593 // Check that we cannot find a port with "HDMI2", because we never added one
594 std::optional<DisplayViewport> hdmi2Viewport = mFakePolicy->getDisplayViewportByPort(hdmi2);
595 ASSERT_FALSE(hdmi2Viewport);
596}
597
Michael Wrightd02c5b62014-02-10 15:10:22 -0800598// --- InputReaderTest ---
599
600class InputReaderTest : public testing::Test {
601protected:
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700602 std::unique_ptr<TestInputListener> mFakeListener;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800603 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou3bc7e092019-07-24 17:43:30 -0700604 std::shared_ptr<FakeEventHub> mFakeEventHub;
Prabir Pradhan28efc192019-11-05 01:10:04 +0000605 std::unique_ptr<InstrumentedInputReader> mReader;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800606
Chris Yea52ade12020-08-27 16:49:20 -0700607 void SetUp() override {
Siarhei Vishniakou3bc7e092019-07-24 17:43:30 -0700608 mFakeEventHub = std::make_unique<FakeEventHub>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700609 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700610 mFakeListener = std::make_unique<TestInputListener>();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800611
Prabir Pradhan28efc192019-11-05 01:10:04 +0000612 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700613 *mFakeListener);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800614 }
615
Chris Yea52ade12020-08-27 16:49:20 -0700616 void TearDown() override {
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700617 mFakeListener.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800618 mFakePolicy.clear();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800619 }
620
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700621 void addDevice(int32_t eventHubId, const std::string& name,
622 ftl::Flags<InputDeviceClass> classes, const PropertyMap* configuration) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800623 mFakeEventHub->addDevice(eventHubId, name, classes);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800624
625 if (configuration) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800626 mFakeEventHub->addConfigurationMap(eventHubId, configuration);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800627 }
628 mFakeEventHub->finishDeviceScan();
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000629 mReader->loopOnce();
630 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700631 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Prabir Pradhane3da4bb2023-04-05 23:51:23 +0000632 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyInputDevicesChangedWasCalled());
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700633 ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800634 }
635
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800636 void disableDevice(int32_t deviceId) {
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700637 mFakePolicy->addDisabledDevice(deviceId);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000638 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::ENABLED_STATE);
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700639 }
640
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800641 void enableDevice(int32_t deviceId) {
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700642 mFakePolicy->removeDisabledDevice(deviceId);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000643 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::ENABLED_STATE);
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700644 }
645
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800646 FakeInputMapper& addDeviceWithFakeInputMapper(int32_t deviceId, int32_t eventHubId,
Chris Ye1b0c7342020-07-28 21:57:03 -0700647 const std::string& name,
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700648 ftl::Flags<InputDeviceClass> classes,
649 uint32_t sources,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800650 const PropertyMap* configuration) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800651 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, name);
Arpit Singh8e6fb252023-04-06 11:49:17 +0000652 FakeInputMapper& mapper =
653 device->addMapper<FakeInputMapper>(eventHubId,
654 mFakePolicy->getReaderConfiguration(), sources);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -0800655 mReader->pushNextDevice(device);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800656 addDevice(eventHubId, name, classes, configuration);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800657 return mapper;
658 }
659};
660
Chris Ye98d3f532020-10-01 21:48:59 -0700661TEST_F(InputReaderTest, PolicyGetInputDevices) {
662 ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard", InputDeviceClass::KEYBOARD, nullptr));
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700663 ASSERT_NO_FATAL_FAILURE(addDevice(2, "ignored", ftl::Flags<InputDeviceClass>(0),
Chris Ye98d3f532020-10-01 21:48:59 -0700664 nullptr)); // no classes so device will be ignored
Michael Wrightd02c5b62014-02-10 15:10:22 -0800665
666 // Should also have received a notification describing the new input devices.
Chris Ye98d3f532020-10-01 21:48:59 -0700667 const std::vector<InputDeviceInfo>& inputDevices = mFakePolicy->getInputDevices();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800668 ASSERT_EQ(1U, inputDevices.size());
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800669 ASSERT_EQ(END_RESERVED_ID + 1, inputDevices[0].getId());
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100670 ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800671 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, inputDevices[0].getKeyboardType());
672 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, inputDevices[0].getSources());
Siarhei Vishniakou1983a712021-06-04 19:27:09 +0000673 ASSERT_EQ(0U, inputDevices[0].getMotionRanges().size());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800674}
675
Vaibhav Devmurari5fc7d852023-03-17 18:43:33 +0000676TEST_F(InputReaderTest, InputDeviceRecreatedOnSysfsNodeChanged) {
677 ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard", InputDeviceClass::KEYBOARD, nullptr));
678 mFakeEventHub->setSysfsRootPath(1, "xyz");
679
680 // Should also have received a notification describing the new input device.
681 ASSERT_EQ(1U, mFakePolicy->getInputDevices().size());
682 InputDeviceInfo inputDevice = mFakePolicy->getInputDevices()[0];
683 ASSERT_EQ(0U, inputDevice.getLights().size());
684
685 RawLightInfo infoMonolight = {.id = 123,
686 .name = "mono_keyboard_backlight",
687 .maxBrightness = 255,
688 .flags = InputLightClass::BRIGHTNESS,
689 .path = ""};
690 mFakeEventHub->addRawLightInfo(/*rawId=*/123, std::move(infoMonolight));
691 mReader->sysfsNodeChanged("xyz");
692 mReader->loopOnce();
693
694 // Should also have received a notification describing the new recreated input device.
695 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
696 inputDevice = mFakePolicy->getInputDevices()[0];
697 ASSERT_EQ(1U, inputDevice.getLights().size());
698}
699
Chris Yee7310032020-09-22 15:36:28 -0700700TEST_F(InputReaderTest, GetMergedInputDevices) {
701 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
702 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
703 // Add two subdevices to device
704 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
705 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000706 device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
707 AINPUT_SOURCE_KEYBOARD);
708 device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
709 AINPUT_SOURCE_KEYBOARD);
Chris Yee7310032020-09-22 15:36:28 -0700710
711 // Push same device instance for next device to be added, so they'll have same identifier.
712 mReader->pushNextDevice(device);
713 mReader->pushNextDevice(device);
714 ASSERT_NO_FATAL_FAILURE(
715 addDevice(eventHubIds[0], "fake1", InputDeviceClass::KEYBOARD, nullptr));
716 ASSERT_NO_FATAL_FAILURE(
717 addDevice(eventHubIds[1], "fake2", InputDeviceClass::KEYBOARD, nullptr));
718
719 // Two devices will be merged to one input device as they have same identifier
Siarhei Vishniakou1983a712021-06-04 19:27:09 +0000720 ASSERT_EQ(1U, mFakePolicy->getInputDevices().size());
Chris Yee7310032020-09-22 15:36:28 -0700721}
722
Chris Yee14523a2020-12-19 13:46:00 -0800723TEST_F(InputReaderTest, GetMergedInputDevicesEnabled) {
724 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
725 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
726 // Add two subdevices to device
727 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
728 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000729 device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
730 AINPUT_SOURCE_KEYBOARD);
731 device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
732 AINPUT_SOURCE_KEYBOARD);
Chris Yee14523a2020-12-19 13:46:00 -0800733
734 // Push same device instance for next device to be added, so they'll have same identifier.
735 mReader->pushNextDevice(device);
736 mReader->pushNextDevice(device);
737 // Sensor device is initially disabled
738 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1",
739 InputDeviceClass::KEYBOARD | InputDeviceClass::SENSOR,
740 nullptr));
741 // Device is disabled because the only sub device is a sensor device and disabled initially.
742 ASSERT_FALSE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
743 ASSERT_FALSE(device->isEnabled());
744 ASSERT_NO_FATAL_FAILURE(
745 addDevice(eventHubIds[1], "fake2", InputDeviceClass::KEYBOARD, nullptr));
746 // The merged device is enabled if any sub device is enabled
747 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
748 ASSERT_TRUE(device->isEnabled());
749}
750
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700751TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800752 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700753 constexpr ftl::Flags<InputDeviceClass> deviceClass(InputDeviceClass::KEYBOARD);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800754 constexpr int32_t eventHubId = 1;
755 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700756 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000757 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
758 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -0800759 mReader->pushNextDevice(device);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800760 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700761
Yi Kong9b14ac62018-07-17 13:48:38 -0700762 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(nullptr));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700763
764 NotifyDeviceResetArgs resetArgs;
765 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700766 ASSERT_EQ(deviceId, resetArgs.deviceId);
767
768 ASSERT_EQ(device->isEnabled(), true);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800769 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000770 mReader->loopOnce();
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700771
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700772 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700773 ASSERT_EQ(deviceId, resetArgs.deviceId);
774 ASSERT_EQ(device->isEnabled(), false);
775
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800776 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000777 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700778 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
779 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasNotCalled());
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700780 ASSERT_EQ(device->isEnabled(), false);
781
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800782 enableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000783 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700784 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700785 ASSERT_EQ(deviceId, resetArgs.deviceId);
786 ASSERT_EQ(device->isEnabled(), true);
787}
788
Michael Wrightd02c5b62014-02-10 15:10:22 -0800789TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800790 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700791 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800792 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800793 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800794 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800795 AINPUT_SOURCE_KEYBOARD, nullptr);
796 mapper.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800797
798 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(0,
799 AINPUT_SOURCE_ANY, AKEYCODE_A))
800 << "Should return unknown when the device id is >= 0 but unknown.";
801
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800802 ASSERT_EQ(AKEY_STATE_UNKNOWN,
803 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
804 << "Should return unknown when the device id is valid but the sources are not "
805 "supported by the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800806
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800807 ASSERT_EQ(AKEY_STATE_DOWN,
808 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
809 AKEYCODE_A))
810 << "Should return value provided by mapper when device id is valid and the device "
811 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800812
813 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(-1,
814 AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
815 << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
816
817 ASSERT_EQ(AKEY_STATE_DOWN, mReader->getKeyCodeState(-1,
818 AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
819 << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
820}
821
Philip Junker4af3b3d2021-12-14 10:36:55 +0100822TEST_F(InputReaderTest, GetKeyCodeForKeyLocation_ForwardsRequestsToMappers) {
823 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
824 constexpr int32_t eventHubId = 1;
825 FakeInputMapper& mapper = addDeviceWithFakeInputMapper(deviceId, eventHubId, "keyboard",
826 InputDeviceClass::KEYBOARD,
827 AINPUT_SOURCE_KEYBOARD, nullptr);
828 mapper.addKeyCodeMapping(AKEYCODE_Y, AKEYCODE_Z);
829
830 ASSERT_EQ(AKEYCODE_UNKNOWN, mReader->getKeyCodeForKeyLocation(0, AKEYCODE_Y))
831 << "Should return unknown when the device with the specified id is not found.";
832
833 ASSERT_EQ(AKEYCODE_Z, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_Y))
834 << "Should return correct mapping when device id is valid and mapping exists.";
835
836 ASSERT_EQ(AKEYCODE_A, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_A))
837 << "Should return the location key code when device id is valid and there's no "
838 "mapping.";
839}
840
841TEST_F(InputReaderTest, GetKeyCodeForKeyLocation_NoKeyboardMapper) {
842 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
843 constexpr int32_t eventHubId = 1;
844 FakeInputMapper& mapper = addDeviceWithFakeInputMapper(deviceId, eventHubId, "joystick",
845 InputDeviceClass::JOYSTICK,
846 AINPUT_SOURCE_GAMEPAD, nullptr);
847 mapper.addKeyCodeMapping(AKEYCODE_Y, AKEYCODE_Z);
848
849 ASSERT_EQ(AKEYCODE_UNKNOWN, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_Y))
850 << "Should return unknown when the device id is valid but there is no keyboard mapper";
851}
852
Michael Wrightd02c5b62014-02-10 15:10:22 -0800853TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800854 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700855 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800856 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800857 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800858 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800859 AINPUT_SOURCE_KEYBOARD, nullptr);
860 mapper.setScanCodeState(KEY_A, AKEY_STATE_DOWN);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800861
862 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(0,
863 AINPUT_SOURCE_ANY, KEY_A))
864 << "Should return unknown when the device id is >= 0 but unknown.";
865
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800866 ASSERT_EQ(AKEY_STATE_UNKNOWN,
867 mReader->getScanCodeState(deviceId, AINPUT_SOURCE_TRACKBALL, KEY_A))
868 << "Should return unknown when the device id is valid but the sources are not "
869 "supported by the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800870
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800871 ASSERT_EQ(AKEY_STATE_DOWN,
872 mReader->getScanCodeState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
873 KEY_A))
874 << "Should return value provided by mapper when device id is valid and the device "
875 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800876
877 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(-1,
878 AINPUT_SOURCE_TRACKBALL, KEY_A))
879 << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
880
881 ASSERT_EQ(AKEY_STATE_DOWN, mReader->getScanCodeState(-1,
882 AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, KEY_A))
883 << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
884}
885
886TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800887 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700888 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800889 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800890 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800891 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800892 AINPUT_SOURCE_KEYBOARD, nullptr);
893 mapper.setSwitchState(SW_LID, AKEY_STATE_DOWN);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800894
895 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(0,
896 AINPUT_SOURCE_ANY, SW_LID))
897 << "Should return unknown when the device id is >= 0 but unknown.";
898
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800899 ASSERT_EQ(AKEY_STATE_UNKNOWN,
900 mReader->getSwitchState(deviceId, AINPUT_SOURCE_TRACKBALL, SW_LID))
901 << "Should return unknown when the device id is valid but the sources are not "
902 "supported by the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800903
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800904 ASSERT_EQ(AKEY_STATE_DOWN,
905 mReader->getSwitchState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
906 SW_LID))
907 << "Should return value provided by mapper when device id is valid and the device "
908 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800909
910 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(-1,
911 AINPUT_SOURCE_TRACKBALL, SW_LID))
912 << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
913
914 ASSERT_EQ(AKEY_STATE_DOWN, mReader->getSwitchState(-1,
915 AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, SW_LID))
916 << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
917}
918
919TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800920 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700921 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800922 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800923 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800924 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800925 AINPUT_SOURCE_KEYBOARD, nullptr);
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100926
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800927 mapper.addSupportedKeyCode(AKEYCODE_A);
928 mapper.addSupportedKeyCode(AKEYCODE_B);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800929
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700930 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800931 uint8_t flags[4] = { 0, 0, 0, 1 };
932
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700933 ASSERT_FALSE(mReader->hasKeys(0, AINPUT_SOURCE_ANY, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800934 << "Should return false when device id is >= 0 but unknown.";
935 ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
936
937 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700938 ASSERT_FALSE(mReader->hasKeys(deviceId, AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800939 << "Should return false when device id is valid but the sources are not supported by "
940 "the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800941 ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
942
943 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700944 ASSERT_TRUE(mReader->hasKeys(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800945 keyCodes, flags))
946 << "Should return value provided by mapper when device id is valid and the device "
947 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800948 ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
949
950 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700951 ASSERT_FALSE(mReader->hasKeys(-1, AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
952 << "Should return false when the device id is < 0 but the sources are not supported by "
953 "any device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800954 ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
955
956 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700957 ASSERT_TRUE(
958 mReader->hasKeys(-1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
959 << "Should return value provided by mapper when device id is < 0 and one of the "
960 "devices supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800961 ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
962}
963
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000964TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChanged) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800965 constexpr int32_t eventHubId = 1;
Chris Ye1b0c7342020-07-28 21:57:03 -0700966 addDevice(eventHubId, "ignored", InputDeviceClass::KEYBOARD, nullptr);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800967
968 NotifyConfigurationChangedArgs args;
969
970 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(&args));
971 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
972}
973
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000974TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800975 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700976 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000977 constexpr nsecs_t when = 0;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800978 constexpr int32_t eventHubId = 1;
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000979 constexpr nsecs_t readTime = 2;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800980 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800981 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800982 AINPUT_SOURCE_KEYBOARD, nullptr);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800983
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000984 mFakeEventHub->enqueueEvent(when, readTime, eventHubId, EV_KEY, KEY_A, 1);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000985 mReader->loopOnce();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800986 ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty());
987
988 RawEvent event;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800989 ASSERT_NO_FATAL_FAILURE(mapper.assertProcessWasCalled(&event));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000990 ASSERT_EQ(when, event.when);
991 ASSERT_EQ(readTime, event.readTime);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800992 ASSERT_EQ(eventHubId, event.deviceId);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800993 ASSERT_EQ(EV_KEY, event.type);
994 ASSERT_EQ(KEY_A, event.code);
995 ASSERT_EQ(1, event.value);
996}
997
Garfield Tan1c7bc862020-01-28 13:24:04 -0800998TEST_F(InputReaderTest, DeviceReset_RandomId) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800999 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001000 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001001 constexpr int32_t eventHubId = 1;
1002 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
Prabir Pradhan42611e02018-11-27 14:04:02 -08001003 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +00001004 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
1005 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001006 mReader->pushNextDevice(device);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001007 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Prabir Pradhan42611e02018-11-27 14:04:02 -08001008
1009 NotifyDeviceResetArgs resetArgs;
1010 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001011 int32_t prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001012
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001013 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001014 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -07001015 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tan1c7bc862020-01-28 13:24:04 -08001016 ASSERT_NE(prevId, resetArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001017 prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001018
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001019 enableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001020 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -07001021 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tan1c7bc862020-01-28 13:24:04 -08001022 ASSERT_NE(prevId, resetArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001023 prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001024
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001025 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001026 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -07001027 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tan1c7bc862020-01-28 13:24:04 -08001028 ASSERT_NE(prevId, resetArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001029 prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001030}
1031
Garfield Tan1c7bc862020-01-28 13:24:04 -08001032TEST_F(InputReaderTest, DeviceReset_GenerateIdWithInputReaderSource) {
1033 constexpr int32_t deviceId = 1;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001034 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Garfield Tan1c7bc862020-01-28 13:24:04 -08001035 constexpr int32_t eventHubId = 1;
1036 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
1037 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +00001038 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
1039 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001040 mReader->pushNextDevice(device);
Garfield Tan1c7bc862020-01-28 13:24:04 -08001041 ASSERT_NO_FATAL_FAILURE(addDevice(deviceId, "fake", deviceClass, nullptr));
1042
1043 NotifyDeviceResetArgs resetArgs;
1044 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1045 ASSERT_EQ(IdGenerator::Source::INPUT_READER, IdGenerator::getSource(resetArgs.id));
1046}
1047
Arthur Hungc23540e2018-11-29 20:42:11 +08001048TEST_F(InputReaderTest, Device_CanDispatchToDisplay) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001049 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001050 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001051 constexpr int32_t eventHubId = 1;
Arthur Hungc23540e2018-11-29 20:42:11 +08001052 const char* DEVICE_LOCATION = "USB1";
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001053 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
1054 FakeInputMapper& mapper =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001055 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
1056 AINPUT_SOURCE_TOUCHSCREEN);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001057 mReader->pushNextDevice(device);
Arthur Hungc23540e2018-11-29 20:42:11 +08001058
1059 const uint8_t hdmi1 = 1;
1060
1061 // Associated touch screen with second display.
1062 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
1063
1064 // Add default and second display.
Prabir Pradhan28efc192019-11-05 01:10:04 +00001065 mFakePolicy->clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00001066 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00001067 /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL);
Arthur Hungc23540e2018-11-29 20:42:11 +08001068 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +00001069 ui::ROTATION_0, /*isActive=*/true, "local:1", hdmi1,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01001070 ViewportType::EXTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001071 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::DISPLAY_INFO);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001072 mReader->loopOnce();
Prabir Pradhan28efc192019-11-05 01:10:04 +00001073
1074 // Add the device, and make sure all of the callbacks are triggered.
1075 // The device is added after the input port associations are processed since
1076 // we do not yet support dynamic device-to-display associations.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001077 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Prabir Pradhan2574dfa2019-10-16 16:35:07 -07001078 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled());
Prabir Pradhan28efc192019-11-05 01:10:04 +00001079 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001080 ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
Arthur Hungc23540e2018-11-29 20:42:11 +08001081
Arthur Hung2c9a3342019-07-23 14:18:59 +08001082 // Device should only dispatch to the specified display.
Arthur Hungc23540e2018-11-29 20:42:11 +08001083 ASSERT_EQ(deviceId, device->getId());
1084 ASSERT_FALSE(mReader->canDispatchToDisplay(deviceId, DISPLAY_ID));
1085 ASSERT_TRUE(mReader->canDispatchToDisplay(deviceId, SECONDARY_DISPLAY_ID));
Arthur Hung2c9a3342019-07-23 14:18:59 +08001086
1087 // Can't dispatch event from a disabled device.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001088 disableDevice(deviceId);
Prabir Pradhan28efc192019-11-05 01:10:04 +00001089 mReader->loopOnce();
Arthur Hung2c9a3342019-07-23 14:18:59 +08001090 ASSERT_FALSE(mReader->canDispatchToDisplay(deviceId, SECONDARY_DISPLAY_ID));
Arthur Hungc23540e2018-11-29 20:42:11 +08001091}
1092
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001093TEST_F(InputReaderTest, WhenEnabledChanges_AllSubdevicesAreUpdated) {
1094 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001095 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001096 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
1097 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
1098 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +00001099 device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
1100 AINPUT_SOURCE_KEYBOARD);
1101 device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
1102 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001103 mReader->pushNextDevice(device);
1104 mReader->pushNextDevice(device);
1105 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1", deviceClass, nullptr));
1106 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[1], "fake2", deviceClass, nullptr));
1107
1108 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(nullptr));
1109
1110 NotifyDeviceResetArgs resetArgs;
1111 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1112 ASSERT_EQ(deviceId, resetArgs.deviceId);
1113 ASSERT_TRUE(device->isEnabled());
1114 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
1115 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
1116
1117 disableDevice(deviceId);
1118 mReader->loopOnce();
1119
1120 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1121 ASSERT_EQ(deviceId, resetArgs.deviceId);
1122 ASSERT_FALSE(device->isEnabled());
1123 ASSERT_FALSE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
1124 ASSERT_FALSE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
1125
1126 enableDevice(deviceId);
1127 mReader->loopOnce();
1128
1129 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1130 ASSERT_EQ(deviceId, resetArgs.deviceId);
1131 ASSERT_TRUE(device->isEnabled());
1132 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
1133 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
1134}
1135
1136TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToSubdeviceMappers) {
1137 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001138 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001139 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
1140 // Add two subdevices to device
1141 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
1142 FakeInputMapper& mapperDevice1 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001143 device->addMapper<FakeInputMapper>(eventHubIds[0],
1144 mFakePolicy->getReaderConfiguration(),
1145 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001146 FakeInputMapper& mapperDevice2 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001147 device->addMapper<FakeInputMapper>(eventHubIds[1],
1148 mFakePolicy->getReaderConfiguration(),
1149 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001150 mReader->pushNextDevice(device);
1151 mReader->pushNextDevice(device);
1152 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1", deviceClass, nullptr));
1153 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[1], "fake2", deviceClass, nullptr));
1154
1155 mapperDevice1.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
1156 mapperDevice2.setKeyCodeState(AKEYCODE_B, AKEY_STATE_DOWN);
1157
1158 ASSERT_EQ(AKEY_STATE_DOWN,
1159 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_A));
1160 ASSERT_EQ(AKEY_STATE_DOWN,
1161 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_B));
1162 ASSERT_EQ(AKEY_STATE_UNKNOWN,
1163 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_C));
1164}
1165
Prabir Pradhan7e186182020-11-10 13:56:45 -08001166TEST_F(InputReaderTest, ChangingPointerCaptureNotifiesInputListener) {
1167 NotifyPointerCaptureChangedArgs args;
1168
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001169 auto request = mFakePolicy->setPointerCapture(true);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001170 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE);
Prabir Pradhan7e186182020-11-10 13:56:45 -08001171 mReader->loopOnce();
1172 mFakeListener->assertNotifyCaptureWasCalled(&args);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001173 ASSERT_TRUE(args.request.enable) << "Pointer Capture should be enabled.";
1174 ASSERT_EQ(args.request, request) << "Pointer Capture sequence number should match.";
Prabir Pradhan7e186182020-11-10 13:56:45 -08001175
1176 mFakePolicy->setPointerCapture(false);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001177 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE);
Prabir Pradhan7e186182020-11-10 13:56:45 -08001178 mReader->loopOnce();
1179 mFakeListener->assertNotifyCaptureWasCalled(&args);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001180 ASSERT_FALSE(args.request.enable) << "Pointer Capture should be disabled.";
Prabir Pradhan7e186182020-11-10 13:56:45 -08001181
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001182 // Verify that the Pointer Capture state is not updated when the configuration value
Prabir Pradhan7e186182020-11-10 13:56:45 -08001183 // does not change.
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001184 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE);
Prabir Pradhan7e186182020-11-10 13:56:45 -08001185 mReader->loopOnce();
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001186 mFakeListener->assertNotifyCaptureWasNotCalled();
Prabir Pradhan7e186182020-11-10 13:56:45 -08001187}
1188
Chris Ye87143712020-11-10 05:05:58 +00001189class FakeVibratorInputMapper : public FakeInputMapper {
1190public:
Arpit Singh8e6fb252023-04-06 11:49:17 +00001191 FakeVibratorInputMapper(InputDeviceContext& deviceContext,
1192 const InputReaderConfiguration& readerConfig, uint32_t sources)
1193 : FakeInputMapper(deviceContext, readerConfig, sources) {}
Chris Ye87143712020-11-10 05:05:58 +00001194
1195 std::vector<int32_t> getVibratorIds() override { return getDeviceContext().getVibratorIds(); }
1196};
1197
1198TEST_F(InputReaderTest, VibratorGetVibratorIds) {
1199 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001200 ftl::Flags<InputDeviceClass> deviceClass =
1201 InputDeviceClass::KEYBOARD | InputDeviceClass::VIBRATOR;
Chris Ye87143712020-11-10 05:05:58 +00001202 constexpr int32_t eventHubId = 1;
1203 const char* DEVICE_LOCATION = "BLUETOOTH";
1204 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
1205 FakeVibratorInputMapper& mapper =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001206 device->addMapper<FakeVibratorInputMapper>(eventHubId,
1207 mFakePolicy->getReaderConfiguration(),
1208 AINPUT_SOURCE_KEYBOARD);
Chris Ye87143712020-11-10 05:05:58 +00001209 mReader->pushNextDevice(device);
1210
1211 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1212 ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
1213
1214 ASSERT_EQ(mapper.getVibratorIds().size(), 2U);
1215 ASSERT_EQ(mReader->getVibratorIds(deviceId).size(), 2U);
1216}
1217
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001218// --- FakePeripheralController ---
Kim Low03ea0352020-11-06 12:45:07 -08001219
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001220class FakePeripheralController : public PeripheralControllerInterface {
Chris Yee2b1e5c2021-03-10 22:45:12 -08001221public:
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001222 FakePeripheralController(InputDeviceContext& deviceContext) : mDeviceContext(deviceContext) {}
Chris Yee2b1e5c2021-03-10 22:45:12 -08001223
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001224 ~FakePeripheralController() override {}
Chris Yee2b1e5c2021-03-10 22:45:12 -08001225
Andy Chenf9f1a022022-08-29 20:07:10 -04001226 int32_t getEventHubId() const { return getDeviceContext().getEventHubId(); }
1227
Chris Yee2b1e5c2021-03-10 22:45:12 -08001228 void populateDeviceInfo(InputDeviceInfo* deviceInfo) override {}
1229
1230 void dump(std::string& dump) override {}
1231
1232 std::optional<int32_t> getBatteryCapacity(int32_t batteryId) override {
1233 return getDeviceContext().getBatteryCapacity(batteryId);
Kim Low03ea0352020-11-06 12:45:07 -08001234 }
1235
Chris Yee2b1e5c2021-03-10 22:45:12 -08001236 std::optional<int32_t> getBatteryStatus(int32_t batteryId) override {
1237 return getDeviceContext().getBatteryStatus(batteryId);
Kim Low03ea0352020-11-06 12:45:07 -08001238 }
Chris Ye3fdbfef2021-01-06 18:45:18 -08001239
1240 bool setLightColor(int32_t lightId, int32_t color) override {
1241 getDeviceContext().setLightBrightness(lightId, color >> 24);
1242 return true;
1243 }
1244
1245 std::optional<int32_t> getLightColor(int32_t lightId) override {
1246 std::optional<int32_t> result = getDeviceContext().getLightBrightness(lightId);
1247 if (!result.has_value()) {
1248 return std::nullopt;
1249 }
1250 return result.value() << 24;
1251 }
Chris Yee2b1e5c2021-03-10 22:45:12 -08001252
1253 bool setLightPlayerId(int32_t lightId, int32_t playerId) override { return true; }
1254
1255 std::optional<int32_t> getLightPlayerId(int32_t lightId) override { return std::nullopt; }
1256
1257private:
1258 InputDeviceContext& mDeviceContext;
1259 inline int32_t getDeviceId() { return mDeviceContext.getId(); }
1260 inline InputDeviceContext& getDeviceContext() { return mDeviceContext; }
Andy Chenf9f1a022022-08-29 20:07:10 -04001261 inline InputDeviceContext& getDeviceContext() const { return mDeviceContext; }
Chris Ye3fdbfef2021-01-06 18:45:18 -08001262};
1263
Chris Yee2b1e5c2021-03-10 22:45:12 -08001264TEST_F(InputReaderTest, BatteryGetCapacity) {
1265 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001266 ftl::Flags<InputDeviceClass> deviceClass =
1267 InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
Chris Yee2b1e5c2021-03-10 22:45:12 -08001268 constexpr int32_t eventHubId = 1;
1269 const char* DEVICE_LOCATION = "BLUETOOTH";
1270 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001271 FakePeripheralController& controller =
1272 device->addController<FakePeripheralController>(eventHubId);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001273 mReader->pushNextDevice(device);
1274
1275 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1276
Harry Cuttsa5b71292022-11-28 12:56:17 +00001277 ASSERT_EQ(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY),
1278 FakeEventHub::BATTERY_CAPACITY);
1279 ASSERT_EQ(mReader->getBatteryCapacity(deviceId), FakeEventHub::BATTERY_CAPACITY);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001280}
1281
1282TEST_F(InputReaderTest, BatteryGetStatus) {
1283 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001284 ftl::Flags<InputDeviceClass> deviceClass =
1285 InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
Chris Yee2b1e5c2021-03-10 22:45:12 -08001286 constexpr int32_t eventHubId = 1;
1287 const char* DEVICE_LOCATION = "BLUETOOTH";
1288 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001289 FakePeripheralController& controller =
1290 device->addController<FakePeripheralController>(eventHubId);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001291 mReader->pushNextDevice(device);
1292
1293 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1294
Harry Cuttsa5b71292022-11-28 12:56:17 +00001295 ASSERT_EQ(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY),
1296 FakeEventHub::BATTERY_STATUS);
1297 ASSERT_EQ(mReader->getBatteryStatus(deviceId), FakeEventHub::BATTERY_STATUS);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001298}
1299
Prabir Pradhane287ecd2022-09-07 21:18:05 +00001300TEST_F(InputReaderTest, BatteryGetDevicePath) {
1301 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
1302 ftl::Flags<InputDeviceClass> deviceClass =
1303 InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
1304 constexpr int32_t eventHubId = 1;
1305 const char* DEVICE_LOCATION = "BLUETOOTH";
1306 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
1307 device->addController<FakePeripheralController>(eventHubId);
1308 mReader->pushNextDevice(device);
1309
1310 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1311
Harry Cuttsa5b71292022-11-28 12:56:17 +00001312 ASSERT_EQ(mReader->getBatteryDevicePath(deviceId), FakeEventHub::BATTERY_DEVPATH);
Prabir Pradhane287ecd2022-09-07 21:18:05 +00001313}
1314
Chris Ye3fdbfef2021-01-06 18:45:18 -08001315TEST_F(InputReaderTest, LightGetColor) {
1316 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001317 ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::LIGHT;
Chris Ye3fdbfef2021-01-06 18:45:18 -08001318 constexpr int32_t eventHubId = 1;
1319 const char* DEVICE_LOCATION = "BLUETOOTH";
1320 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001321 FakePeripheralController& controller =
1322 device->addController<FakePeripheralController>(eventHubId);
Chris Ye3fdbfef2021-01-06 18:45:18 -08001323 mReader->pushNextDevice(device);
1324 RawLightInfo info = {.id = 1,
1325 .name = "Mono",
1326 .maxBrightness = 255,
1327 .flags = InputLightClass::BRIGHTNESS,
1328 .path = ""};
Harry Cutts33476232023-01-30 19:57:29 +00001329 mFakeEventHub->addRawLightInfo(/*rawId=*/1, std::move(info));
1330 mFakeEventHub->fakeLightBrightness(/*rawId=*/1, 0x55);
Chris Ye3fdbfef2021-01-06 18:45:18 -08001331
1332 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Chris Ye3fdbfef2021-01-06 18:45:18 -08001333
Harry Cutts33476232023-01-30 19:57:29 +00001334 ASSERT_TRUE(controller.setLightColor(/*lightId=*/1, LIGHT_BRIGHTNESS));
1335 ASSERT_EQ(controller.getLightColor(/*lightId=*/1), LIGHT_BRIGHTNESS);
1336 ASSERT_TRUE(mReader->setLightColor(deviceId, /*lightId=*/1, LIGHT_BRIGHTNESS));
1337 ASSERT_EQ(mReader->getLightColor(deviceId, /*lightId=*/1), LIGHT_BRIGHTNESS);
Chris Ye3fdbfef2021-01-06 18:45:18 -08001338}
1339
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001340// --- InputReaderIntegrationTest ---
1341
1342// These tests create and interact with the InputReader only through its interface.
1343// The InputReader is started during SetUp(), which starts its processing in its own
1344// thread. The tests use linux uinput to emulate input devices.
1345// NOTE: Interacting with the physical device while these tests are running may cause
1346// the tests to fail.
1347class InputReaderIntegrationTest : public testing::Test {
1348protected:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001349 std::unique_ptr<TestInputListener> mTestListener;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001350 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001351 std::unique_ptr<InputReaderInterface> mReader;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001352
Prabir Pradhan2853b7a2021-08-23 14:08:51 +00001353 std::shared_ptr<FakePointerController> mFakePointerController;
1354
Prabir Pradhanafb7d612024-01-08 22:45:24 +00001355 constexpr static auto EVENT_HAPPENED_TIMEOUT = 2000ms;
1356 constexpr static auto EVENT_DID_NOT_HAPPEN_TIMEOUT = 30ms;
1357
Chris Yea52ade12020-08-27 16:49:20 -07001358 void SetUp() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001359#if !defined(__ANDROID__)
1360 GTEST_SKIP();
1361#endif
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001362 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Prabir Pradhan2853b7a2021-08-23 14:08:51 +00001363 mFakePointerController = std::make_shared<FakePointerController>();
1364 mFakePolicy->setPointerController(mFakePointerController);
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001365
Arpit Singh440bf652023-08-09 09:23:43 +00001366 setupInputReader();
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001367 }
1368
Chris Yea52ade12020-08-27 16:49:20 -07001369 void TearDown() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001370#if !defined(__ANDROID__)
1371 return;
1372#endif
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001373 ASSERT_EQ(mReader->stop(), OK);
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001374 mReader.reset();
1375 mTestListener.reset();
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001376 mFakePolicy.clear();
1377 }
Prabir Pradhanda20b172022-09-26 17:01:18 +00001378
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001379 std::optional<InputDeviceInfo> waitForDevice(const std::string& deviceName) {
1380 std::chrono::time_point start = std::chrono::steady_clock::now();
1381 while (true) {
1382 const std::vector<InputDeviceInfo> inputDevices = mFakePolicy->getInputDevices();
1383 const auto& it = std::find_if(inputDevices.begin(), inputDevices.end(),
1384 [&deviceName](const InputDeviceInfo& info) {
1385 return info.getIdentifier().name == deviceName;
1386 });
1387 if (it != inputDevices.end()) {
1388 return std::make_optional(*it);
1389 }
1390 std::this_thread::sleep_for(1ms);
1391 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
1392 if (elapsed > 5s) {
1393 return {};
1394 }
1395 }
Prabir Pradhanda20b172022-09-26 17:01:18 +00001396 }
Arpit Singh440bf652023-08-09 09:23:43 +00001397
1398 void setupInputReader() {
Prabir Pradhanafb7d612024-01-08 22:45:24 +00001399 mTestListener = std::make_unique<TestInputListener>(EVENT_HAPPENED_TIMEOUT,
1400 EVENT_DID_NOT_HAPPEN_TIMEOUT);
Arpit Singh440bf652023-08-09 09:23:43 +00001401
1402 mReader = std::make_unique<InputReader>(std::make_shared<EventHub>(), mFakePolicy,
1403 *mTestListener);
1404 ASSERT_EQ(mReader->start(), OK);
1405
1406 // Since this test is run on a real device, all the input devices connected
1407 // to the test device will show up in mReader. We wait for those input devices to
1408 // show up before beginning the tests.
1409 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1410 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyInputDevicesChangedWasCalled());
1411 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
1412 }
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001413};
1414
1415TEST_F(InputReaderIntegrationTest, TestInvalidDevice) {
1416 // An invalid input device that is only used for this test.
1417 class InvalidUinputDevice : public UinputDevice {
1418 public:
Harry Cutts33476232023-01-30 19:57:29 +00001419 InvalidUinputDevice() : UinputDevice("Invalid Device", /*productId=*/99) {}
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001420
1421 private:
1422 void configureDevice(int fd, uinput_user_dev* device) override {}
1423 };
1424
1425 const size_t numDevices = mFakePolicy->getInputDevices().size();
1426
1427 // UinputDevice does not set any event or key bits, so InputReader should not
1428 // consider it as a valid device.
1429 std::unique_ptr<UinputDevice> invalidDevice = createUinputDevice<InvalidUinputDevice>();
1430 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesNotChanged());
1431 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasNotCalled());
1432 ASSERT_EQ(numDevices, mFakePolicy->getInputDevices().size());
1433
1434 invalidDevice.reset();
1435 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesNotChanged());
1436 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasNotCalled());
1437 ASSERT_EQ(numDevices, mFakePolicy->getInputDevices().size());
1438}
1439
1440TEST_F(InputReaderIntegrationTest, AddNewDevice) {
1441 const size_t initialNumDevices = mFakePolicy->getInputDevices().size();
1442
1443 std::unique_ptr<UinputHomeKey> keyboard = createUinputDevice<UinputHomeKey>();
1444 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1445 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
1446 ASSERT_EQ(initialNumDevices + 1, mFakePolicy->getInputDevices().size());
1447
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001448 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001449 ASSERT_TRUE(device.has_value());
1450 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, device->getKeyboardType());
1451 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources());
1452 ASSERT_EQ(0U, device->getMotionRanges().size());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001453
1454 keyboard.reset();
1455 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1456 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
1457 ASSERT_EQ(initialNumDevices, mFakePolicy->getInputDevices().size());
1458}
1459
1460TEST_F(InputReaderIntegrationTest, SendsEventsToInputListener) {
1461 std::unique_ptr<UinputHomeKey> keyboard = createUinputDevice<UinputHomeKey>();
1462 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1463
1464 NotifyConfigurationChangedArgs configChangedArgs;
1465 ASSERT_NO_FATAL_FAILURE(
1466 mTestListener->assertNotifyConfigurationChangedWasCalled(&configChangedArgs));
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001467 int32_t prevId = configChangedArgs.id;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001468 nsecs_t prevTimestamp = configChangedArgs.eventTime;
1469
1470 NotifyKeyArgs keyArgs;
1471 keyboard->pressAndReleaseHomeKey();
1472 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs));
1473 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
Garfield Tan1c7bc862020-01-28 13:24:04 -08001474 ASSERT_NE(prevId, keyArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001475 prevId = keyArgs.id;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001476 ASSERT_LE(prevTimestamp, keyArgs.eventTime);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001477 ASSERT_LE(keyArgs.eventTime, keyArgs.readTime);
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001478 prevTimestamp = keyArgs.eventTime;
1479
1480 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs));
1481 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
Garfield Tan1c7bc862020-01-28 13:24:04 -08001482 ASSERT_NE(prevId, keyArgs.id);
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001483 ASSERT_LE(prevTimestamp, keyArgs.eventTime);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001484 ASSERT_LE(keyArgs.eventTime, keyArgs.readTime);
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001485}
Michael Wrightd02c5b62014-02-10 15:10:22 -08001486
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001487TEST_F(InputReaderIntegrationTest, ExternalStylusesButtons) {
1488 std::unique_ptr<UinputExternalStylus> stylus = createUinputDevice<UinputExternalStylus>();
1489 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1490
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001491 const auto device = waitForDevice(stylus->getName());
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001492 ASSERT_TRUE(device.has_value());
1493
Prabir Pradhana3621852022-10-14 18:57:23 +00001494 // An external stylus with buttons should also be recognized as a keyboard.
1495 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_STYLUS, device->getSources())
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001496 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1497 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, device->getKeyboardType());
1498
1499 const auto DOWN =
1500 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD));
1501 const auto UP = AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD));
1502
1503 stylus->pressAndReleaseKey(BTN_STYLUS);
1504 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1505 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
1506 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1507 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
1508
1509 stylus->pressAndReleaseKey(BTN_STYLUS2);
1510 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1511 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_SECONDARY))));
1512 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1513 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_SECONDARY))));
1514
1515 stylus->pressAndReleaseKey(BTN_STYLUS3);
1516 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1517 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_TERTIARY))));
1518 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1519 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_TERTIARY))));
1520}
1521
Prabir Pradhan3c28b942023-08-18 20:02:01 +00001522TEST_F(InputReaderIntegrationTest, KeyboardWithStylusButtons) {
1523 std::unique_ptr<UinputKeyboard> keyboard =
1524 createUinputDevice<UinputKeyboard>("KeyboardWithStylusButtons", /*productId=*/99,
1525 std::initializer_list<int>{KEY_Q, KEY_W, KEY_E,
1526 KEY_R, KEY_T, KEY_Y,
1527 BTN_STYLUS, BTN_STYLUS2,
1528 BTN_STYLUS3});
1529 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1530
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001531 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhan3c28b942023-08-18 20:02:01 +00001532 ASSERT_TRUE(device.has_value());
1533
1534 // An alphabetical keyboard that reports stylus buttons should not be recognized as a stylus.
1535 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources())
1536 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1537 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, device->getKeyboardType());
1538}
1539
Prabir Pradhan37a819b2023-08-22 23:20:16 +00001540TEST_F(InputReaderIntegrationTest, HidUsageKeyboardIsNotAStylus) {
1541 // Create a Uinput keyboard that simulates a keyboard that can report HID usage codes. The
1542 // hid-input driver reports HID usage codes using the value for EV_MSC MSC_SCAN event.
1543 std::unique_ptr<UinputKeyboardWithHidUsage> keyboard =
1544 createUinputDevice<UinputKeyboardWithHidUsage>(
1545 std::initializer_list<int>{KEY_VOLUMEUP, KEY_VOLUMEDOWN});
1546 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1547
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001548 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhan37a819b2023-08-22 23:20:16 +00001549 ASSERT_TRUE(device.has_value());
1550
1551 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources())
1552 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1553
1554 // If a device supports reporting HID usage codes, it shouldn't automatically support
1555 // stylus keys.
1556 const std::vector<int> keycodes{AKEYCODE_STYLUS_BUTTON_PRIMARY};
1557 uint8_t outFlags[] = {0};
1558 ASSERT_TRUE(mReader->hasKeys(device->getId(), AINPUT_SOURCE_KEYBOARD, keycodes, outFlags));
1559 ASSERT_EQ(0, outFlags[0]) << "Keyboard should not have stylus button";
1560}
1561
Siarhei Vishniakoua0d2b802020-05-13 14:00:31 -07001562/**
1563 * The Steam controller sends BTN_GEAR_DOWN and BTN_GEAR_UP for the two "paddle" buttons
1564 * on the back. In this test, we make sure that BTN_GEAR_DOWN / BTN_WHEEL and BTN_GEAR_UP
1565 * are passed to the listener.
1566 */
1567static_assert(BTN_GEAR_DOWN == BTN_WHEEL);
1568TEST_F(InputReaderIntegrationTest, SendsGearDownAndUpToInputListener) {
1569 std::unique_ptr<UinputSteamController> controller = createUinputDevice<UinputSteamController>();
1570 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1571 NotifyKeyArgs keyArgs;
1572
1573 controller->pressAndReleaseKey(BTN_GEAR_DOWN);
1574 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_DOWN
1575 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_UP
1576 ASSERT_EQ(BTN_GEAR_DOWN, keyArgs.scanCode);
1577
1578 controller->pressAndReleaseKey(BTN_GEAR_UP);
1579 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_DOWN
1580 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_UP
1581 ASSERT_EQ(BTN_GEAR_UP, keyArgs.scanCode);
1582}
1583
Prabir Pradhan484d55a2022-10-14 23:17:16 +00001584// --- TouchIntegrationTest ---
1585
Arpit Singh440bf652023-08-09 09:23:43 +00001586class BaseTouchIntegrationTest : public InputReaderIntegrationTest {
Arthur Hungaab25622020-01-16 11:22:11 +08001587protected:
Arthur Hungaab25622020-01-16 11:22:11 +08001588 const std::string UNIQUE_ID = "local:0";
1589
Chris Yea52ade12020-08-27 16:49:20 -07001590 void SetUp() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001591#if !defined(__ANDROID__)
1592 GTEST_SKIP();
1593#endif
Arthur Hungaab25622020-01-16 11:22:11 +08001594 InputReaderIntegrationTest::SetUp();
1595 // At least add an internal display.
Michael Wrighta9cf4192022-12-01 23:46:39 +00001596 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
1597 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Arthur Hungaab25622020-01-16 11:22:11 +08001598
1599 mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT));
1600 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1601 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001602 const auto info = waitForDevice(mDevice->getName());
Prabir Pradhanda20b172022-09-26 17:01:18 +00001603 ASSERT_TRUE(info);
1604 mDeviceInfo = *info;
Arthur Hungaab25622020-01-16 11:22:11 +08001605 }
1606
1607 void setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
Michael Wrighta9cf4192022-12-01 23:46:39 +00001608 ui::Rotation orientation, const std::string& uniqueId,
Arthur Hungaab25622020-01-16 11:22:11 +08001609 std::optional<uint8_t> physicalPort,
1610 ViewportType viewportType) {
Harry Cutts33476232023-01-30 19:57:29 +00001611 mFakePolicy->addDisplayViewport(displayId, width, height, orientation, /*isActive=*/true,
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00001612 uniqueId, physicalPort, viewportType);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001613 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hungaab25622020-01-16 11:22:11 +08001614 }
1615
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001616 void assertReceivedMotion(int32_t action, const std::vector<Point>& points) {
1617 NotifyMotionArgs args;
1618 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1619 EXPECT_EQ(action, args.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07001620 ASSERT_EQ(points.size(), args.getPointerCount());
1621 for (size_t i = 0; i < args.getPointerCount(); i++) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001622 EXPECT_EQ(points[i].x, args.pointerCoords[i].getX());
1623 EXPECT_EQ(points[i].y, args.pointerCoords[i].getY());
1624 }
1625 }
1626
Arthur Hungaab25622020-01-16 11:22:11 +08001627 std::unique_ptr<UinputTouchScreen> mDevice;
Prabir Pradhanda20b172022-09-26 17:01:18 +00001628 InputDeviceInfo mDeviceInfo;
Arthur Hungaab25622020-01-16 11:22:11 +08001629};
1630
Arpit Singh440bf652023-08-09 09:23:43 +00001631enum class TouchIntegrationTestDisplays { DISPLAY_INTERNAL, DISPLAY_INPUT_PORT, DISPLAY_UNIQUE_ID };
1632
1633class TouchIntegrationTest : public BaseTouchIntegrationTest,
1634 public testing::WithParamInterface<TouchIntegrationTestDisplays> {
1635protected:
1636 static constexpr std::optional<uint8_t> DISPLAY_PORT = 0;
1637 const std::string INPUT_PORT = "uinput_touch/input0";
1638
1639 void SetUp() override {
1640#if !defined(__ANDROID__)
1641 GTEST_SKIP();
1642#endif
1643 if (GetParam() == TouchIntegrationTestDisplays::DISPLAY_INTERNAL) {
1644 BaseTouchIntegrationTest::SetUp();
1645 return;
1646 }
1647
1648 // setup policy with a input-port or UniqueId association to the display
1649 bool isInputPortAssociation =
1650 GetParam() == TouchIntegrationTestDisplays::DISPLAY_INPUT_PORT;
1651
1652 mFakePolicy = sp<FakeInputReaderPolicy>::make();
1653 if (isInputPortAssociation) {
1654 mFakePolicy->addInputPortAssociation(INPUT_PORT, DISPLAY_PORT.value());
1655 } else {
1656 mFakePolicy->addInputUniqueIdAssociation(INPUT_PORT, UNIQUE_ID);
1657 }
1658 mFakePointerController = std::make_shared<FakePointerController>();
1659 mFakePolicy->setPointerController(mFakePointerController);
1660
1661 InputReaderIntegrationTest::setupInputReader();
1662
1663 mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT),
1664 INPUT_PORT);
1665 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1666
1667 // Add a display linked to a physical port or UniqueId.
1668 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
1669 UNIQUE_ID, isInputPortAssociation ? DISPLAY_PORT : NO_PORT,
1670 ViewportType::INTERNAL);
1671 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1672 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001673 const auto info = waitForDevice(mDevice->getName());
Arpit Singh440bf652023-08-09 09:23:43 +00001674 ASSERT_TRUE(info);
1675 mDeviceInfo = *info;
1676 }
1677};
1678
1679TEST_P(TouchIntegrationTest, MultiTouchDeviceSource) {
Prabir Pradhanf9a41282022-10-25 17:15:50 +00001680 // The UinputTouchScreen is an MT device that supports MT_TOOL_TYPE and also supports stylus
1681 // buttons. It should show up as a touchscreen, stylus, and keyboard (for reporting button
1682 // presses).
1683 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD,
1684 mDeviceInfo.getSources());
1685}
1686
Arpit Singh440bf652023-08-09 09:23:43 +00001687TEST_P(TouchIntegrationTest, InputEvent_ProcessSingleTouch) {
Arthur Hungaab25622020-01-16 11:22:11 +08001688 NotifyMotionArgs args;
1689 const Point centerPoint = mDevice->getCenterPoint();
1690
1691 // ACTION_DOWN
Arthur Hung9ad18942021-06-19 02:04:46 +00001692 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001693 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001694 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001695 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1696 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1697
1698 // ACTION_MOVE
1699 mDevice->sendMove(centerPoint + Point(1, 1));
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001700 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001701 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1702 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1703
1704 // ACTION_UP
1705 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001706 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001707 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1708 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
1709}
1710
Arpit Singh440bf652023-08-09 09:23:43 +00001711TEST_P(TouchIntegrationTest, InputEvent_ProcessMultiTouch) {
Arthur Hungaab25622020-01-16 11:22:11 +08001712 NotifyMotionArgs args;
1713 const Point centerPoint = mDevice->getCenterPoint();
1714
1715 // ACTION_DOWN
Arthur Hung9ad18942021-06-19 02:04:46 +00001716 mDevice->sendSlot(FIRST_SLOT);
1717 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001718 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001719 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001720 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1721 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1722
1723 // ACTION_POINTER_DOWN (Second slot)
1724 const Point secondPoint = centerPoint + Point(100, 100);
1725 mDevice->sendSlot(SECOND_SLOT);
1726 mDevice->sendTrackingId(SECOND_TRACKING_ID);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001727 mDevice->sendDown(secondPoint);
1728 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001729 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001730 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001731
1732 // ACTION_MOVE (Second slot)
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001733 mDevice->sendMove(secondPoint + Point(1, 1));
1734 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001735 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1736 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1737
1738 // ACTION_POINTER_UP (Second slot)
arthurhungcc7f9802020-04-30 17:55:40 +08001739 mDevice->sendPointerUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001740 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001741 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001742 ASSERT_EQ(ACTION_POINTER_1_UP, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001743
1744 // ACTION_UP
1745 mDevice->sendSlot(FIRST_SLOT);
1746 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001747 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001748 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1749 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
1750}
1751
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001752/**
1753 * What happens when a pointer goes up while another pointer moves in the same frame? Are POINTER_UP
1754 * events guaranteed to contain the same data as a preceding MOVE, or can they contain different
1755 * data?
1756 * In this test, we try to send a change in coordinates in Pointer 0 in the same frame as the
1757 * liftoff of Pointer 1. We check that POINTER_UP event is generated first, and the MOVE event
1758 * for Pointer 0 only is generated after.
1759 * Suppose we are only interested in learning the movement of Pointer 0. If we only observe MOVE
1760 * events, we will not miss any information.
1761 * Even though the Pointer 1 up event contains updated Pointer 0 coordinates, there is another MOVE
1762 * event generated afterwards that contains the newest movement of pointer 0.
1763 * This is important for palm rejection. If there is a subsequent InputListener stage that detects
1764 * palms, and wants to cancel Pointer 1, then it is safe to simply drop POINTER_1_UP event without
1765 * losing information about non-palm pointers.
1766 */
Arpit Singh440bf652023-08-09 09:23:43 +00001767TEST_P(TouchIntegrationTest, MultiTouch_PointerMoveAndSecondPointerUp) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001768 NotifyMotionArgs args;
1769 const Point centerPoint = mDevice->getCenterPoint();
1770
1771 // ACTION_DOWN
1772 mDevice->sendSlot(FIRST_SLOT);
1773 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1774 mDevice->sendDown(centerPoint);
1775 mDevice->sendSync();
1776 assertReceivedMotion(AMOTION_EVENT_ACTION_DOWN, {centerPoint});
1777
1778 // ACTION_POINTER_DOWN (Second slot)
1779 const Point secondPoint = centerPoint + Point(100, 100);
1780 mDevice->sendSlot(SECOND_SLOT);
1781 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1782 mDevice->sendDown(secondPoint);
1783 mDevice->sendSync();
1784 assertReceivedMotion(ACTION_POINTER_1_DOWN, {centerPoint, secondPoint});
1785
1786 // ACTION_MOVE (First slot)
1787 mDevice->sendSlot(FIRST_SLOT);
1788 mDevice->sendMove(centerPoint + Point(5, 5));
1789 // ACTION_POINTER_UP (Second slot)
1790 mDevice->sendSlot(SECOND_SLOT);
1791 mDevice->sendPointerUp();
1792 // Send a single sync for the above 2 pointer updates
1793 mDevice->sendSync();
1794
1795 // First, we should get POINTER_UP for the second pointer
1796 assertReceivedMotion(ACTION_POINTER_1_UP,
1797 {/*first pointer */ centerPoint + Point(5, 5),
1798 /*second pointer*/ secondPoint});
1799
1800 // Next, the MOVE event for the first pointer
1801 assertReceivedMotion(AMOTION_EVENT_ACTION_MOVE, {centerPoint + Point(5, 5)});
1802}
1803
1804/**
1805 * Similar scenario as above. The difference is that when the second pointer goes up, it will first
1806 * move, and then it will go up, all in the same frame.
1807 * In this scenario, the movement of the second pointer just prior to liftoff is ignored, and never
1808 * gets sent to the listener.
1809 */
Arpit Singh440bf652023-08-09 09:23:43 +00001810TEST_P(TouchIntegrationTest, MultiTouch_PointerMoveAndSecondPointerMoveAndUp) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001811 NotifyMotionArgs args;
1812 const Point centerPoint = mDevice->getCenterPoint();
1813
1814 // ACTION_DOWN
1815 mDevice->sendSlot(FIRST_SLOT);
1816 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1817 mDevice->sendDown(centerPoint);
1818 mDevice->sendSync();
1819 assertReceivedMotion(AMOTION_EVENT_ACTION_DOWN, {centerPoint});
1820
1821 // ACTION_POINTER_DOWN (Second slot)
1822 const Point secondPoint = centerPoint + Point(100, 100);
1823 mDevice->sendSlot(SECOND_SLOT);
1824 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1825 mDevice->sendDown(secondPoint);
1826 mDevice->sendSync();
1827 assertReceivedMotion(ACTION_POINTER_1_DOWN, {centerPoint, secondPoint});
1828
1829 // ACTION_MOVE (First slot)
1830 mDevice->sendSlot(FIRST_SLOT);
1831 mDevice->sendMove(centerPoint + Point(5, 5));
1832 // ACTION_POINTER_UP (Second slot)
1833 mDevice->sendSlot(SECOND_SLOT);
1834 mDevice->sendMove(secondPoint + Point(6, 6));
1835 mDevice->sendPointerUp();
1836 // Send a single sync for the above 2 pointer updates
1837 mDevice->sendSync();
1838
1839 // First, we should get POINTER_UP for the second pointer
1840 // The movement of the second pointer during the liftoff frame is ignored.
1841 // The coordinates 'secondPoint + Point(6, 6)' are never sent to the listener.
1842 assertReceivedMotion(ACTION_POINTER_1_UP,
1843 {/*first pointer */ centerPoint + Point(5, 5),
1844 /*second pointer*/ secondPoint});
1845
1846 // Next, the MOVE event for the first pointer
1847 assertReceivedMotion(AMOTION_EVENT_ACTION_MOVE, {centerPoint + Point(5, 5)});
1848}
1849
Arpit Singh440bf652023-08-09 09:23:43 +00001850TEST_P(TouchIntegrationTest, InputEvent_ProcessPalm) {
Arthur Hungaab25622020-01-16 11:22:11 +08001851 NotifyMotionArgs args;
1852 const Point centerPoint = mDevice->getCenterPoint();
1853
1854 // ACTION_DOWN
arthurhungcc7f9802020-04-30 17:55:40 +08001855 mDevice->sendSlot(FIRST_SLOT);
1856 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001857 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001858 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001859 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1860 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1861
arthurhungcc7f9802020-04-30 17:55:40 +08001862 // ACTION_POINTER_DOWN (second slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001863 const Point secondPoint = centerPoint + Point(100, 100);
1864 mDevice->sendSlot(SECOND_SLOT);
1865 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1866 mDevice->sendDown(secondPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001867 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001868 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001869 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001870
arthurhungcc7f9802020-04-30 17:55:40 +08001871 // ACTION_MOVE (second slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001872 mDevice->sendMove(secondPoint + Point(1, 1));
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001873 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001874 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1875 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1876
arthurhungcc7f9802020-04-30 17:55:40 +08001877 // Send MT_TOOL_PALM (second slot), which indicates that the touch IC has determined this to be
1878 // a palm event.
1879 // Expect to receive the ACTION_POINTER_UP with cancel flag.
Arthur Hungaab25622020-01-16 11:22:11 +08001880 mDevice->sendToolType(MT_TOOL_PALM);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001881 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001882 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001883 ASSERT_EQ(ACTION_POINTER_1_UP, args.action);
arthurhungcc7f9802020-04-30 17:55:40 +08001884 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, args.flags);
Arthur Hungaab25622020-01-16 11:22:11 +08001885
arthurhungcc7f9802020-04-30 17:55:40 +08001886 // Send up to second slot, expect first slot send moving.
1887 mDevice->sendPointerUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001888 mDevice->sendSync();
arthurhungcc7f9802020-04-30 17:55:40 +08001889 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1890 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001891
arthurhungcc7f9802020-04-30 17:55:40 +08001892 // Send ACTION_UP (first slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001893 mDevice->sendSlot(FIRST_SLOT);
1894 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001895 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001896
arthurhungcc7f9802020-04-30 17:55:40 +08001897 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1898 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001899}
1900
Prabir Pradhanc09ec6d2023-08-14 22:31:43 +00001901/**
1902 * Some drivers historically have reported axis values outside of the range specified in the
1903 * evdev axis info. Ensure we don't crash when this happens. For example, a driver may report a
1904 * pressure value greater than the reported maximum, since it unclear what specific meaning the
1905 * maximum value for pressure has (beyond the maximum value that can be produced by a sensor),
1906 * and no units for pressure (resolution) is specified by the evdev documentation.
1907 */
1908TEST_P(TouchIntegrationTest, AcceptsAxisValuesOutsideReportedRange) {
1909 const Point centerPoint = mDevice->getCenterPoint();
1910
1911 // Down with pressure outside the reported range
1912 mDevice->sendSlot(FIRST_SLOT);
1913 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1914 mDevice->sendDown(centerPoint);
1915 mDevice->sendPressure(UinputTouchScreen::RAW_PRESSURE_MAX + 2);
1916 mDevice->sendSync();
1917 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1918 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
1919
1920 // Move to a point outside the reported range
1921 mDevice->sendMove(Point(DISPLAY_WIDTH, DISPLAY_HEIGHT) + Point(1, 1));
1922 mDevice->sendSync();
1923 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1924 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
1925
1926 // Up
1927 mDevice->sendUp();
1928 mDevice->sendSync();
1929 ASSERT_NO_FATAL_FAILURE(
1930 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
1931}
1932
Arpit Singh440bf652023-08-09 09:23:43 +00001933TEST_P(TouchIntegrationTest, NotifiesPolicyWhenStylusGestureStarted) {
Prabir Pradhanda20b172022-09-26 17:01:18 +00001934 const Point centerPoint = mDevice->getCenterPoint();
1935
1936 // Send down with the pen tool selected. The policy should be notified of the stylus presence.
1937 mDevice->sendSlot(FIRST_SLOT);
1938 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1939 mDevice->sendToolType(MT_TOOL_PEN);
1940 mDevice->sendDown(centerPoint);
1941 mDevice->sendSync();
1942 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1943 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001944 WithToolType(ToolType::STYLUS))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00001945
1946 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotified(mDeviceInfo.getId()));
1947
1948 // Release the stylus touch.
1949 mDevice->sendUp();
1950 mDevice->sendSync();
1951 ASSERT_NO_FATAL_FAILURE(
1952 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
1953
1954 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotNotified());
1955
1956 // Touch down with the finger, without the pen tool selected. The policy is not notified.
1957 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1958 mDevice->sendToolType(MT_TOOL_FINGER);
1959 mDevice->sendDown(centerPoint);
1960 mDevice->sendSync();
1961 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1962 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001963 WithToolType(ToolType::FINGER))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00001964
1965 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotNotified());
1966
1967 mDevice->sendUp();
1968 mDevice->sendSync();
1969 ASSERT_NO_FATAL_FAILURE(
1970 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
1971
1972 // Send a move event with the stylus tool without BTN_TOUCH to generate a hover enter.
1973 // The policy should be notified of the stylus presence.
1974 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1975 mDevice->sendToolType(MT_TOOL_PEN);
1976 mDevice->sendMove(centerPoint);
1977 mDevice->sendSync();
1978 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1979 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001980 WithToolType(ToolType::STYLUS))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00001981
1982 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotified(mDeviceInfo.getId()));
1983}
1984
Arpit Singh440bf652023-08-09 09:23:43 +00001985TEST_P(TouchIntegrationTest, ExternalStylusConnectedDuringTouchGesture) {
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00001986 const Point centerPoint = mDevice->getCenterPoint();
1987
1988 // Down
1989 mDevice->sendSlot(FIRST_SLOT);
1990 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1991 mDevice->sendDown(centerPoint);
1992 mDevice->sendSync();
1993 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1994 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
1995
1996 // Move
1997 mDevice->sendMove(centerPoint + Point(1, 1));
1998 mDevice->sendSync();
1999 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2000 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
2001
2002 // Connecting an external stylus mid-gesture should not interrupt the ongoing gesture stream.
2003 auto externalStylus = createUinputDevice<UinputExternalStylus>();
2004 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
2005 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002006 const auto stylusInfo = waitForDevice(externalStylus->getName());
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002007 ASSERT_TRUE(stylusInfo);
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002008
2009 // Move
2010 mDevice->sendMove(centerPoint + Point(2, 2));
2011 mDevice->sendSync();
2012 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2013 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
2014
2015 // Disconnecting an external stylus mid-gesture should not interrupt the ongoing gesture stream.
2016 externalStylus.reset();
2017 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
2018 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
2019 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2020
2021 // Up
2022 mDevice->sendUp();
2023 mDevice->sendSync();
2024 ASSERT_NO_FATAL_FAILURE(
2025 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2026
2027 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2028}
2029
Arpit Singh440bf652023-08-09 09:23:43 +00002030INSTANTIATE_TEST_SUITE_P(TouchIntegrationTestDisplayVariants, TouchIntegrationTest,
2031 testing::Values(TouchIntegrationTestDisplays::DISPLAY_INTERNAL,
2032 TouchIntegrationTestDisplays::DISPLAY_INPUT_PORT,
2033 TouchIntegrationTestDisplays::DISPLAY_UNIQUE_ID));
2034
Prabir Pradhan124ea442022-10-28 20:27:44 +00002035// --- StylusButtonIntegrationTest ---
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002036
Prabir Pradhan124ea442022-10-28 20:27:44 +00002037// Verify the behavior of button presses reported by various kinds of styluses, including buttons
2038// reported by the touchscreen's device, by a fused external stylus, and by an un-fused external
2039// stylus.
2040template <typename UinputStylusDevice>
Arpit Singh440bf652023-08-09 09:23:43 +00002041class StylusButtonIntegrationTest : public BaseTouchIntegrationTest {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002042protected:
2043 void SetUp() override {
2044#if !defined(__ANDROID__)
2045 GTEST_SKIP();
2046#endif
Arpit Singh440bf652023-08-09 09:23:43 +00002047 BaseTouchIntegrationTest::SetUp();
Prabir Pradhan124ea442022-10-28 20:27:44 +00002048 mTouchscreen = mDevice.get();
2049 mTouchscreenInfo = mDeviceInfo;
2050
2051 setUpStylusDevice();
2052 }
2053
2054 UinputStylusDevice* mStylus{nullptr};
2055 InputDeviceInfo mStylusInfo{};
2056
2057 UinputTouchScreen* mTouchscreen{nullptr};
2058 InputDeviceInfo mTouchscreenInfo{};
2059
2060private:
2061 // When we are attempting to test stylus button events that are sent from the touchscreen,
2062 // use the same Uinput device for the touchscreen and the stylus.
2063 template <typename T = UinputStylusDevice>
2064 std::enable_if_t<std::is_same_v<UinputTouchScreen, T>, void> setUpStylusDevice() {
2065 mStylus = mDevice.get();
2066 mStylusInfo = mDeviceInfo;
2067 }
2068
2069 // When we are attempting to stylus buttons from an external stylus being merged with touches
2070 // from a touchscreen, create a new Uinput device through which stylus buttons can be injected.
2071 template <typename T = UinputStylusDevice>
2072 std::enable_if_t<!std::is_same_v<UinputTouchScreen, T>, void> setUpStylusDevice() {
2073 mStylusDeviceLifecycleTracker = createUinputDevice<T>();
2074 mStylus = mStylusDeviceLifecycleTracker.get();
2075 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
2076 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002077 const auto info = waitForDevice(mStylus->getName());
Prabir Pradhan124ea442022-10-28 20:27:44 +00002078 ASSERT_TRUE(info);
2079 mStylusInfo = *info;
2080 }
2081
2082 std::unique_ptr<UinputStylusDevice> mStylusDeviceLifecycleTracker{};
2083
2084 // Hide the base class's device to expose it with a different name for readability.
Arpit Singh440bf652023-08-09 09:23:43 +00002085 using BaseTouchIntegrationTest::mDevice;
2086 using BaseTouchIntegrationTest::mDeviceInfo;
Prabir Pradhan124ea442022-10-28 20:27:44 +00002087};
2088
2089using StylusButtonIntegrationTestTypes =
2090 ::testing::Types<UinputTouchScreen, UinputExternalStylus, UinputExternalStylusWithPressure>;
2091TYPED_TEST_SUITE(StylusButtonIntegrationTest, StylusButtonIntegrationTestTypes);
2092
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002093TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsGenerateKeyEvents) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002094 const auto stylusId = TestFixture::mStylusInfo.getId();
2095
2096 TestFixture::mStylus->pressKey(BTN_STYLUS);
2097 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2098 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2099 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2100
2101 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2102 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002103 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002104 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002105}
2106
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002107TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingTouchGesture) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002108 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2109 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2110 const auto stylusId = TestFixture::mStylusInfo.getId();
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002111
2112 // Press the stylus button.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002113 TestFixture::mStylus->pressKey(BTN_STYLUS);
2114 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002115 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002116 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002117
2118 // Start and finish a stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002119 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2120 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2121 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2122 TestFixture::mTouchscreen->sendDown(centerPoint);
2123 TestFixture::mTouchscreen->sendSync();
2124 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002125 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002126 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002127 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2128 WithDeviceId(touchscreenId))));
2129 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002130 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002131 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002132 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2133 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002134
Prabir Pradhan124ea442022-10-28 20:27:44 +00002135 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2136 TestFixture::mTouchscreen->sendSync();
2137 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002138 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002139 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002140 WithDeviceId(touchscreenId))));
2141 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002142 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002143 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002144 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002145
2146 // Release the stylus button.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002147 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2148 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002149 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002150 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002151}
2152
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002153TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingHoveringTouchGesture) {
Prabir Pradhan9a561c22022-11-07 16:11:23 +00002154 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2155 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2156 const auto stylusId = TestFixture::mStylusInfo.getId();
2157 auto toolTypeDevice =
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002158 AllOf(WithToolType(ToolType::STYLUS), WithDeviceId(touchscreenId));
Prabir Pradhan9a561c22022-11-07 16:11:23 +00002159
2160 // Press the stylus button.
2161 TestFixture::mStylus->pressKey(BTN_STYLUS);
2162 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2163 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2164 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2165
2166 // Start hovering with the stylus.
2167 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2168 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2169 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2170 TestFixture::mTouchscreen->sendMove(centerPoint);
2171 TestFixture::mTouchscreen->sendSync();
2172 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2173 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2174 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2175 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2176 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2177 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2178 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2179 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
2180 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2181
2182 // Touch down with the stylus.
2183 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2184 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2185 TestFixture::mTouchscreen->sendDown(centerPoint);
2186 TestFixture::mTouchscreen->sendSync();
2187 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2188 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
2189 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2190
2191 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2192 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
2193 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2194
2195 // Stop touching with the stylus, and start hovering.
2196 TestFixture::mTouchscreen->sendUp();
2197 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2198 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2199 TestFixture::mTouchscreen->sendMove(centerPoint);
2200 TestFixture::mTouchscreen->sendSync();
2201 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2202 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_UP),
2203 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2204 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2205 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2206 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2207 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2208 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2209 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2210
2211 // Stop hovering.
2212 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2213 TestFixture::mTouchscreen->sendSync();
2214 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2215 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
2216 WithButtonState(0))));
2217 // TODO(b/257971675): Fix inconsistent button state when exiting hover.
2218 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2219 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
2220 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2221
2222 // Release the stylus button.
2223 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2224 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2225 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
2226 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2227}
2228
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002229TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsWithinTouchGesture) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002230 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2231 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2232 const auto stylusId = TestFixture::mStylusInfo.getId();
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002233
2234 // Start a stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002235 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2236 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2237 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2238 TestFixture::mTouchscreen->sendDown(centerPoint);
2239 TestFixture::mTouchscreen->sendSync();
2240 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002241 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002242 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002243 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002244
2245 // Press and release a stylus button. Each change in button state also generates a MOVE event.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002246 TestFixture::mStylus->pressKey(BTN_STYLUS);
2247 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002248 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002249 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2250 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002251 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002252 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002253 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2254 WithDeviceId(touchscreenId))));
2255 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002256 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002257 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002258 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2259 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002260
Prabir Pradhan124ea442022-10-28 20:27:44 +00002261 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2262 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002263 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002264 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2265 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002266 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002267 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002268 WithDeviceId(touchscreenId))));
2269 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002270 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002271 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002272 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002273
2274 // Finish the stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002275 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2276 TestFixture::mTouchscreen->sendSync();
2277 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002278 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002279 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002280 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002281}
2282
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002283TYPED_TEST(StylusButtonIntegrationTest, StylusButtonMotionEventsDisabled) {
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002284 TestFixture::mFakePolicy->setStylusButtonMotionEventsEnabled(false);
2285 TestFixture::mReader->requestRefreshConfiguration(
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002286 InputReaderConfiguration::Change::STYLUS_BUTTON_REPORTING);
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002287
2288 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2289 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2290 const auto stylusId = TestFixture::mStylusInfo.getId();
2291
2292 // Start a stylus gesture. By the time this event is processed, the configuration change that
2293 // was requested is guaranteed to be completed.
2294 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2295 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2296 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2297 TestFixture::mTouchscreen->sendDown(centerPoint);
2298 TestFixture::mTouchscreen->sendSync();
2299 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2300 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002301 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002302 WithDeviceId(touchscreenId))));
2303
2304 // Press and release a stylus button. Each change only generates a MOVE motion event.
2305 // Key events are unaffected.
2306 TestFixture::mStylus->pressKey(BTN_STYLUS);
2307 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2308 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2309 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2310 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2311 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002312 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002313 WithDeviceId(touchscreenId))));
2314
2315 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2316 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2317 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
2318 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2319 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2320 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002321 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002322 WithDeviceId(touchscreenId))));
2323
2324 // Finish the stylus gesture.
2325 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2326 TestFixture::mTouchscreen->sendSync();
2327 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2328 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002329 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002330 WithDeviceId(touchscreenId))));
2331}
2332
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002333// --- ExternalStylusIntegrationTest ---
2334
2335// Verify the behavior of an external stylus. An external stylus can report pressure or button
2336// data independently of the touchscreen, which is then sent as a MotionEvent as part of an
2337// ongoing stylus gesture that is being emitted by the touchscreen.
Arpit Singh440bf652023-08-09 09:23:43 +00002338using ExternalStylusIntegrationTest = BaseTouchIntegrationTest;
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002339
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002340TEST_F(ExternalStylusIntegrationTest, ExternalStylusConnectionChangesTouchscreenSource) {
2341 // Create an external stylus capable of reporting pressure data that
2342 // should be fused with a touch pointer.
2343 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2344 createUinputDevice<UinputExternalStylusWithPressure>();
2345 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
2346 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002347 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002348 ASSERT_TRUE(stylusInfo);
2349
2350 // Connecting an external stylus changes the source of the touchscreen.
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002351 const auto deviceInfo = waitForDevice(mDevice->getName());
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002352 ASSERT_TRUE(deviceInfo);
2353 ASSERT_TRUE(isFromSource(deviceInfo->getSources(), STYLUS_FUSION_SOURCE));
2354}
2355
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002356TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureReported) {
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002357 const Point centerPoint = mDevice->getCenterPoint();
2358
2359 // Create an external stylus capable of reporting pressure data that
2360 // should be fused with a touch pointer.
2361 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2362 createUinputDevice<UinputExternalStylusWithPressure>();
2363 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
2364 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002365 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002366 ASSERT_TRUE(stylusInfo);
2367
2368 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2369
2370 const auto touchscreenId = mDeviceInfo.getId();
2371
2372 // Set a pressure value on the stylus. It doesn't generate any events.
2373 const auto& RAW_PRESSURE_MAX = UinputExternalStylusWithPressure::RAW_PRESSURE_MAX;
2374 stylus->setPressure(100);
2375 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2376
2377 // Start a finger gesture, and ensure it shows up as stylus gesture
2378 // with the pressure set by the external stylus.
Dominik Laskowski2f01d772022-03-23 16:01:29 -07002379 mDevice->sendSlot(FIRST_SLOT);
Chris Ye1b0c7342020-07-28 21:57:03 -07002380 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002381 mDevice->sendToolType(MT_TOOL_FINGER);
Prabir Pradhanb54ffb22022-10-27 18:03:34 +00002382 mDevice->sendDown(centerPoint);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002383 mDevice->sendSync();
2384 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002385 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithToolType(ToolType::STYLUS),
2386 WithButtonState(0), WithSource(STYLUS_FUSION_SOURCE), WithDeviceId(touchscreenId),
2387 WithPressure(100.f / RAW_PRESSURE_MAX))));
Dominik Laskowski2f01d772022-03-23 16:01:29 -07002388
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002389 // Change the pressure on the external stylus, and ensure the touchscreen generates a MOVE
2390 // event with the updated pressure.
2391 stylus->setPressure(200);
Vaibhav Devmuraridd82b8e2022-08-16 15:34:01 +00002392 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002393 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithToolType(ToolType::STYLUS),
2394 WithButtonState(0), WithSource(STYLUS_FUSION_SOURCE), WithDeviceId(touchscreenId),
2395 WithPressure(200.f / RAW_PRESSURE_MAX))));
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002396
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002397 // The external stylus did not generate any events.
2398 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2399 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
2400}
2401
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002402TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureNotReported) {
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002403 const Point centerPoint = mDevice->getCenterPoint();
2404
2405 // Create an external stylus capable of reporting pressure data that
2406 // should be fused with a touch pointer.
2407 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2408 createUinputDevice<UinputExternalStylusWithPressure>();
2409 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
2410 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002411 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002412 ASSERT_TRUE(stylusInfo);
2413
2414 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2415
2416 const auto touchscreenId = mDeviceInfo.getId();
2417
2418 // Set a pressure value of 0 on the stylus. It doesn't generate any events.
2419 const auto& RAW_PRESSURE_MAX = UinputExternalStylusWithPressure::RAW_PRESSURE_MAX;
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002420 // Send a non-zero value first to prevent the kernel from consuming the zero event.
2421 stylus->setPressure(100);
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002422 stylus->setPressure(0);
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002423 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002424
2425 // Start a finger gesture. The touch device will withhold generating any touches for
2426 // up to 72 milliseconds while waiting for pressure data from the external stylus.
2427 mDevice->sendSlot(FIRST_SLOT);
2428 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2429 mDevice->sendToolType(MT_TOOL_FINGER);
2430 mDevice->sendDown(centerPoint);
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002431 const auto syncTime = std::chrono::system_clock::now();
2432 // After 72 ms, the event *will* be generated. If we wait the full 72 ms to check that NO event
2433 // is generated in that period, there will be a race condition between the event being generated
2434 // and the test's wait timeout expiring. Thus, we wait for a shorter duration in the test, which
2435 // will reduce the liklihood of the race condition occurring.
2436 const auto waitUntilTimeForNoEvent =
2437 syncTime + std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT / 2));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07002438 mDevice->sendSync();
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002439 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled(waitUntilTimeForNoEvent));
Michael Wrightd02c5b62014-02-10 15:10:22 -08002440
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002441 // Since the external stylus did not report a pressure value within the timeout,
2442 // it shows up as a finger pointer.
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002443 const auto waitUntilTimeForEvent = syncTime +
2444 std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT)) + EVENT_HAPPENED_TIMEOUT;
2445 ASSERT_NO_FATAL_FAILURE(
2446 mTestListener->assertNotifyMotionWasCalled(AllOf(WithMotionAction(
2447 AMOTION_EVENT_ACTION_DOWN),
2448 WithSource(AINPUT_SOURCE_TOUCHSCREEN |
2449 AINPUT_SOURCE_STYLUS),
2450 WithToolType(ToolType::FINGER),
2451 WithDeviceId(touchscreenId),
2452 WithPressure(1.f)),
2453 waitUntilTimeForEvent));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002454
2455 // Change the pressure on the external stylus. Since the pressure was not present at the start
2456 // of the gesture, it is ignored for now.
2457 stylus->setPressure(200);
2458 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2459
2460 // Finish the finger gesture.
Michael Wrightd02c5b62014-02-10 15:10:22 -08002461 mDevice->sendTrackingId(INVALID_TRACKING_ID);
2462 mDevice->sendSync();
2463 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2464 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002465 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002466 WithToolType(ToolType::FINGER))));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002467
2468 // Start a new gesture. Since we have a valid pressure value, it shows up as a stylus.
2469 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2470 mDevice->sendToolType(MT_TOOL_FINGER);
2471 mDevice->sendDown(centerPoint);
2472 mDevice->sendSync();
2473 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002474 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithSource(STYLUS_FUSION_SOURCE),
2475 WithToolType(ToolType::STYLUS), WithButtonState(0), WithDeviceId(touchscreenId),
2476 WithPressure(200.f / RAW_PRESSURE_MAX))));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002477
2478 // The external stylus did not generate any events.
2479 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2480 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002481}
Siarhei Vishniakou1983a712021-06-04 19:27:09 +00002482
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002483TEST_F(ExternalStylusIntegrationTest, UnfusedExternalStylus) {
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002484 const Point centerPoint = mDevice->getCenterPoint();
2485
2486 // Create an external stylus device that does not support pressure. It should not affect any
2487 // touch pointers.
2488 std::unique_ptr<UinputExternalStylus> stylus = createUinputDevice<UinputExternalStylus>();
2489 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
2490 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002491 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002492 ASSERT_TRUE(stylusInfo);
2493
2494 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2495
2496 const auto touchscreenId = mDeviceInfo.getId();
2497
2498 // Start a finger gesture and ensure a finger pointer is generated for it, without waiting for
2499 // 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);
2504 auto waitUntil = std::chrono::system_clock::now() +
2505 std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT));
2506 mDevice->sendSync();
2507 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002508 mTestListener->assertNotifyMotionWasCalled(AllOf(WithMotionAction(
2509 AMOTION_EVENT_ACTION_DOWN),
2510 WithToolType(ToolType::FINGER),
2511 WithSource(AINPUT_SOURCE_TOUCHSCREEN |
2512 AINPUT_SOURCE_STYLUS),
2513 WithButtonState(0),
2514 WithDeviceId(touchscreenId),
2515 WithPressure(1.f)),
2516 waitUntil));
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002517
2518 // The external stylus did not generate any events.
2519 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2520 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
2521}
2522
Michael Wrightd02c5b62014-02-10 15:10:22 -08002523// --- InputDeviceTest ---
2524class InputDeviceTest : public testing::Test {
2525protected:
2526 static const char* DEVICE_NAME;
2527 static const char* DEVICE_LOCATION;
2528 static const int32_t DEVICE_ID;
2529 static const int32_t DEVICE_GENERATION;
2530 static const int32_t DEVICE_CONTROLLER_NUMBER;
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002531 static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002532 static const int32_t EVENTHUB_ID;
2533 static const std::string DEVICE_BLUETOOTH_ADDRESS;
2534
2535 std::shared_ptr<FakeEventHub> mFakeEventHub;
2536 sp<FakeInputReaderPolicy> mFakePolicy;
2537 std::unique_ptr<TestInputListener> mFakeListener;
2538 std::unique_ptr<InstrumentedInputReader> mReader;
2539 std::shared_ptr<InputDevice> mDevice;
2540
2541 void SetUp() override {
2542 mFakeEventHub = std::make_unique<FakeEventHub>();
2543 mFakePolicy = sp<FakeInputReaderPolicy>::make();
2544 mFakeListener = std::make_unique<TestInputListener>();
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002545 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Michael Wrightd02c5b62014-02-10 15:10:22 -08002546 *mFakeListener);
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002547 InputDeviceIdentifier identifier;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002548 identifier.name = DEVICE_NAME;
2549 identifier.location = DEVICE_LOCATION;
2550 identifier.bluetoothAddress = DEVICE_BLUETOOTH_ADDRESS;
2551 mDevice = std::make_shared<InputDevice>(mReader->getContext(), DEVICE_ID, DEVICE_GENERATION,
2552 identifier);
2553 mReader->pushNextDevice(mDevice);
2554 mFakeEventHub->addDevice(EVENTHUB_ID, DEVICE_NAME, ftl::Flags<InputDeviceClass>(0));
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002555 mReader->loopOnce();
Michael Wrightd02c5b62014-02-10 15:10:22 -08002556 }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002557
2558 void TearDown() override {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002559 mFakeListener.reset();
2560 mFakePolicy.clear();
2561 }
2562};
2563
2564const char* InputDeviceTest::DEVICE_NAME = "device";
2565const char* InputDeviceTest::DEVICE_LOCATION = "USB1";
2566const int32_t InputDeviceTest::DEVICE_ID = END_RESERVED_ID + 1000;
2567const int32_t InputDeviceTest::DEVICE_GENERATION = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002568const int32_t InputDeviceTest::DEVICE_CONTROLLER_NUMBER = 0;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002569const ftl::Flags<InputDeviceClass> InputDeviceTest::DEVICE_CLASSES =
2570 InputDeviceClass::KEYBOARD | InputDeviceClass::TOUCH | InputDeviceClass::JOYSTICK;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002571const int32_t InputDeviceTest::EVENTHUB_ID = 1;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002572const std::string InputDeviceTest::DEVICE_BLUETOOTH_ADDRESS = "11:AA:22:BB:33:CC";
2573
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002574TEST_F(InputDeviceTest, ImmutableProperties) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002575 ASSERT_EQ(DEVICE_ID, mDevice->getId());
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002576 ASSERT_STREQ(DEVICE_NAME, mDevice->getName().c_str());
2577 ASSERT_EQ(ftl::Flags<InputDeviceClass>(0), mDevice->getClasses());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002578}
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002579
Michael Wrightd02c5b62014-02-10 15:10:22 -08002580TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsFalse) {
2581 ASSERT_EQ(mDevice->isEnabled(), false);
2582}
2583
2584TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
2585 // Configuration.
2586 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002587 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002588
2589 // Reset.
2590 unused += mDevice->reset(ARBITRARY_TIME);
2591
2592 NotifyDeviceResetArgs resetArgs;
2593 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
2594 ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
2595 ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
2596
2597 // Metadata.
2598 ASSERT_TRUE(mDevice->isIgnored());
2599 ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mDevice->getSources());
2600
2601 InputDeviceInfo info = mDevice->getDeviceInfo();
2602 ASSERT_EQ(DEVICE_ID, info.getId());
2603 ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.c_str());
2604 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NONE, info.getKeyboardType());
2605 ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, info.getSources());
2606
2607 // State queries.
2608 ASSERT_EQ(0, mDevice->getMetaState());
2609
2610 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, 0))
2611 << "Ignored device should return unknown key code state.";
2612 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 0))
2613 << "Ignored device should return unknown scan code state.";
2614 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 0))
2615 << "Ignored device should return unknown switch state.";
2616
2617 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B};
2618 uint8_t flags[2] = { 0, 1 };
2619 ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, keyCodes, flags))
2620 << "Ignored device should never mark any key codes.";
2621 ASSERT_EQ(0, flags[0]) << "Flag for unsupported key should be unchanged.";
2622 ASSERT_EQ(1, flags[1]) << "Flag for unsupported key should be unchanged.";
2623}
2624
2625TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRequestsToMappers) {
2626 // Configuration.
2627 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "key", "value");
2628
2629 FakeInputMapper& mapper1 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00002630 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2631 AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002632 mapper1.setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC);
2633 mapper1.setMetaState(AMETA_ALT_ON);
2634 mapper1.addSupportedKeyCode(AKEYCODE_A);
2635 mapper1.addSupportedKeyCode(AKEYCODE_B);
2636 mapper1.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
2637 mapper1.setKeyCodeState(AKEYCODE_B, AKEY_STATE_UP);
2638 mapper1.setScanCodeState(2, AKEY_STATE_DOWN);
2639 mapper1.setScanCodeState(3, AKEY_STATE_UP);
2640 mapper1.setSwitchState(4, AKEY_STATE_DOWN);
2641
2642 FakeInputMapper& mapper2 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00002643 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2644 AINPUT_SOURCE_TOUCHSCREEN);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002645 mapper2.setMetaState(AMETA_SHIFT_ON);
2646
2647 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002648 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002649
Harry Cuttsf13161a2023-03-08 14:15:49 +00002650 std::optional<std::string> propertyValue = mDevice->getConfiguration().getString("key");
2651 ASSERT_TRUE(propertyValue.has_value())
Michael Wrightd02c5b62014-02-10 15:10:22 -08002652 << "Device should have read configuration during configuration phase.";
Harry Cuttsf13161a2023-03-08 14:15:49 +00002653 ASSERT_EQ("value", *propertyValue);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002654
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002655 ASSERT_NO_FATAL_FAILURE(mapper1.assertConfigureWasCalled());
2656 ASSERT_NO_FATAL_FAILURE(mapper2.assertConfigureWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002657
2658 // Reset
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002659 unused += mDevice->reset(ARBITRARY_TIME);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002660 ASSERT_NO_FATAL_FAILURE(mapper1.assertResetWasCalled());
2661 ASSERT_NO_FATAL_FAILURE(mapper2.assertResetWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002662
2663 NotifyDeviceResetArgs resetArgs;
2664 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
2665 ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
2666 ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
2667
2668 // Metadata.
2669 ASSERT_FALSE(mDevice->isIgnored());
2670 ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), mDevice->getSources());
2671
Siarhei Vishniakou1983a712021-06-04 19:27:09 +00002672 InputDeviceInfo info = mDevice->getDeviceInfo();
Michael Wrightd02c5b62014-02-10 15:10:22 -08002673 ASSERT_EQ(DEVICE_ID, info.getId());
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002674 ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002675 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, info.getKeyboardType());
2676 ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), info.getSources());
2677
2678 // State queries.
2679 ASSERT_EQ(AMETA_ALT_ON | AMETA_SHIFT_ON, mDevice->getMetaState())
2680 << "Should query mappers and combine meta states.";
2681
2682 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2683 << "Should return unknown key code state when source not supported.";
2684 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2685 << "Should return unknown scan code state when source not supported.";
2686 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2687 << "Should return unknown switch state when source not supported.";
2688
2689 ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, AKEYCODE_A))
2690 << "Should query mapper when source is supported.";
2691 ASSERT_EQ(AKEY_STATE_UP, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 3))
2692 << "Should query mapper when source is supported.";
2693 ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 4))
2694 << "Should query mapper when source is supported.";
2695
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002696 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2};
Michael Wrightd02c5b62014-02-10 15:10:22 -08002697 uint8_t flags[4] = { 0, 0, 0, 1 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002698 ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -08002699 << "Should do nothing when source is unsupported.";
2700 ASSERT_EQ(0, flags[0]) << "Flag should be unchanged when source is unsupported.";
2701 ASSERT_EQ(0, flags[1]) << "Flag should be unchanged when source is unsupported.";
2702 ASSERT_EQ(0, flags[2]) << "Flag should be unchanged when source is unsupported.";
2703 ASSERT_EQ(1, flags[3]) << "Flag should be unchanged when source is unsupported.";
2704
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002705 ASSERT_TRUE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -08002706 << "Should query mapper when source is supported.";
2707 ASSERT_EQ(1, flags[0]) << "Flag for supported key should be set.";
2708 ASSERT_EQ(1, flags[1]) << "Flag for supported key should be set.";
2709 ASSERT_EQ(0, flags[2]) << "Flag for unsupported key should be unchanged.";
2710 ASSERT_EQ(1, flags[3]) << "Flag for unsupported key should be unchanged.";
2711
2712 // Event handling.
2713 RawEvent event;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002714 event.deviceId = EVENTHUB_ID;
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002715 unused += mDevice->process(&event, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002716
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002717 ASSERT_NO_FATAL_FAILURE(mapper1.assertProcessWasCalled());
2718 ASSERT_NO_FATAL_FAILURE(mapper2.assertProcessWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002719}
2720
Yeabkal Wubshitb1b96db2024-01-24 12:47:00 -08002721TEST_F(InputDeviceTest, Configure_SmoothScrollViewBehaviorNotSet) {
2722 // Set some behavior to force the configuration to be update.
2723 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "1");
2724 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2725 AINPUT_SOURCE_KEYBOARD);
2726
2727 std::list<NotifyArgs> unused =
2728 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2729 /*changes=*/{});
2730
2731 ASSERT_FALSE(mDevice->getDeviceInfo().getViewBehavior().shouldSmoothScroll.has_value());
2732}
2733
2734TEST_F(InputDeviceTest, Configure_SmoothScrollViewBehaviorEnabled) {
2735 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.viewBehavior_smoothScroll", "1");
2736 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2737 AINPUT_SOURCE_KEYBOARD);
2738
2739 std::list<NotifyArgs> unused =
2740 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2741 /*changes=*/{});
2742
2743 ASSERT_TRUE(mDevice->getDeviceInfo().getViewBehavior().shouldSmoothScroll.value_or(false));
2744}
2745
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -07002746TEST_F(InputDeviceTest, WakeDevice_AddsWakeFlagToProcessNotifyArgs) {
2747 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "1");
2748 FakeInputMapper& mapper =
2749 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2750 AINPUT_SOURCE_KEYBOARD);
2751 NotifyMotionArgs args1;
2752 NotifySwitchArgs args2;
2753 NotifyKeyArgs args3;
2754 mapper.setProcessResult({args1, args2, args3});
2755
2756 InputReaderConfiguration config;
2757 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2758
2759 RawEvent event;
2760 event.deviceId = EVENTHUB_ID;
2761 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2762
2763 for (auto& arg : notifyArgs) {
2764 if (const auto notifyMotionArgs = std::get_if<NotifyMotionArgs>(&arg)) {
2765 ASSERT_EQ(POLICY_FLAG_WAKE, notifyMotionArgs->policyFlags);
2766 } else if (const auto notifySwitchArgs = std::get_if<NotifySwitchArgs>(&arg)) {
2767 ASSERT_EQ(POLICY_FLAG_WAKE, notifySwitchArgs->policyFlags);
2768 } else if (const auto notifyKeyArgs = std::get_if<NotifyKeyArgs>(&arg)) {
2769 ASSERT_EQ(POLICY_FLAG_WAKE, notifyKeyArgs->policyFlags);
2770 }
2771 }
2772}
2773
2774TEST_F(InputDeviceTest, NotWakeDevice_DoesNotAddWakeFlagToProcessNotifyArgs) {
2775 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "0");
2776 FakeInputMapper& mapper =
2777 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2778 AINPUT_SOURCE_KEYBOARD);
2779 NotifyMotionArgs args;
2780 mapper.setProcessResult({args});
2781
2782 InputReaderConfiguration config;
2783 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2784
2785 RawEvent event;
2786 event.deviceId = EVENTHUB_ID;
2787 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2788
2789 // POLICY_FLAG_WAKE is not added to the NotifyArgs.
2790 ASSERT_EQ(0u, std::get<NotifyMotionArgs>(notifyArgs.front()).policyFlags);
2791}
2792
2793TEST_F(InputDeviceTest, NotWakeDevice_DoesNotRemoveExistingWakeFlagFromProcessNotifyArgs) {
2794 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "0");
2795 FakeInputMapper& mapper =
2796 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2797 AINPUT_SOURCE_KEYBOARD);
2798 NotifyMotionArgs args;
2799 args.policyFlags = POLICY_FLAG_WAKE;
2800 mapper.setProcessResult({args});
2801
2802 InputReaderConfiguration config;
2803 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2804
2805 RawEvent event;
2806 event.deviceId = EVENTHUB_ID;
2807 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2808
2809 // The POLICY_FLAG_WAKE is preserved, despite the device being a non-wake device.
2810 ASSERT_EQ(POLICY_FLAG_WAKE, std::get<NotifyMotionArgs>(notifyArgs.front()).policyFlags);
2811}
2812
Arthur Hung2c9a3342019-07-23 14:18:59 +08002813// A single input device is associated with a specific display. Check that:
2814// 1. Device is disabled if the viewport corresponding to the associated display is not found
Arpit Singh48189772023-05-30 14:12:49 +00002815// 2. Device is disabled when configure API is called
Arthur Hung2c9a3342019-07-23 14:18:59 +08002816TEST_F(InputDeviceTest, Configure_AssignsDisplayPort) {
Arpit Singh8e6fb252023-04-06 11:49:17 +00002817 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2818 AINPUT_SOURCE_TOUCHSCREEN);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002819
2820 // First Configuration.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002821 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002822 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2823 /*changes=*/{});
Arthur Hung2c9a3342019-07-23 14:18:59 +08002824
2825 // Device should be enabled by default.
2826 ASSERT_TRUE(mDevice->isEnabled());
2827
2828 // Prepare associated info.
2829 constexpr uint8_t hdmi = 1;
2830 const std::string UNIQUE_ID = "local:1";
2831
2832 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002833 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002834 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002835 // Device should be disabled because it is associated with a specific display via
2836 // input port <-> display port association, but the corresponding display is not found
2837 ASSERT_FALSE(mDevice->isEnabled());
2838
2839 // Prepare displays.
2840 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +00002841 ui::ROTATION_0, /*isActive=*/true, UNIQUE_ID, hdmi,
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00002842 ViewportType::INTERNAL);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002843 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002844 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002845 ASSERT_TRUE(mDevice->isEnabled());
2846
2847 // Device should be disabled after set disable.
2848 mFakePolicy->addDisabledDevice(mDevice->getId());
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002849 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002850 InputReaderConfiguration::Change::ENABLED_STATE);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002851 ASSERT_FALSE(mDevice->isEnabled());
2852
2853 // Device should still be disabled even found the associated display.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002854 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002855 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002856 ASSERT_FALSE(mDevice->isEnabled());
2857}
Michael Wrightd02c5b62014-02-10 15:10:22 -08002858
Christine Franks1ba71cc2021-04-07 14:37:42 -07002859TEST_F(InputDeviceTest, Configure_AssignsDisplayUniqueId) {
2860 // Device should be enabled by default.
2861 mFakePolicy->clearViewports();
Arpit Singh8e6fb252023-04-06 11:49:17 +00002862 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2863 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002864 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002865 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2866 /*changes=*/{});
Christine Franks1ba71cc2021-04-07 14:37:42 -07002867 ASSERT_TRUE(mDevice->isEnabled());
2868
2869 // Device should be disabled because it is associated with a specific display, but the
2870 // corresponding display is not found.
Christine Franks2a2293c2022-01-18 11:51:16 -08002871 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002872 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002873 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002874 ASSERT_FALSE(mDevice->isEnabled());
2875
2876 // Device should be enabled when a display is found.
2877 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00002878 ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
Christine Franks1ba71cc2021-04-07 14:37:42 -07002879 NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002880 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002881 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002882 ASSERT_TRUE(mDevice->isEnabled());
2883
2884 // Device should be disabled after set disable.
2885 mFakePolicy->addDisabledDevice(mDevice->getId());
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002886 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002887 InputReaderConfiguration::Change::ENABLED_STATE);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002888 ASSERT_FALSE(mDevice->isEnabled());
2889
2890 // Device should still be disabled even found the associated display.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002891 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002892 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002893 ASSERT_FALSE(mDevice->isEnabled());
2894}
2895
Christine Franks2a2293c2022-01-18 11:51:16 -08002896TEST_F(InputDeviceTest, Configure_UniqueId_CorrectlyMatches) {
2897 mFakePolicy->clearViewports();
Arpit Singh8e6fb252023-04-06 11:49:17 +00002898 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2899 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002900 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002901 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2902 /*changes=*/{});
Christine Franks2a2293c2022-01-18 11:51:16 -08002903
Christine Franks2a2293c2022-01-18 11:51:16 -08002904 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
2905 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00002906 ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
Christine Franks2a2293c2022-01-18 11:51:16 -08002907 NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan55c5ee22024-02-14 06:03:02 +00002908 const auto initialGeneration = mDevice->getGeneration();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002909 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002910 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks2a2293c2022-01-18 11:51:16 -08002911 ASSERT_EQ(DISPLAY_UNIQUE_ID, mDevice->getAssociatedDisplayUniqueId());
Prabir Pradhan55c5ee22024-02-14 06:03:02 +00002912 ASSERT_GT(mDevice->getGeneration(), initialGeneration);
2913 ASSERT_EQ(mDevice->getDeviceInfo().getAssociatedDisplayId(), SECONDARY_DISPLAY_ID);
Christine Franks2a2293c2022-01-18 11:51:16 -08002914}
2915
Siarhei Vishniakou30feb8c2022-09-28 10:48:29 -07002916/**
2917 * This test reproduces a crash caused by a dangling reference that remains after device is added
2918 * and removed. The reference is accessed in InputDevice::dump(..);
2919 */
2920TEST_F(InputDeviceTest, DumpDoesNotCrash) {
2921 constexpr int32_t TEST_EVENTHUB_ID = 10;
2922 mFakeEventHub->addDevice(TEST_EVENTHUB_ID, "Test EventHub device", InputDeviceClass::BATTERY);
2923
Harry Cutts33476232023-01-30 19:57:29 +00002924 InputDevice device(mReader->getContext(), /*id=*/1, /*generation=*/2, /*identifier=*/{});
Arpit Singh82f29a12023-06-13 15:05:53 +00002925 auto _ = device.addEventHubDevice(ARBITRARY_TIME, TEST_EVENTHUB_ID,
2926 mFakePolicy->getReaderConfiguration());
Siarhei Vishniakou30feb8c2022-09-28 10:48:29 -07002927 device.removeEventHubDevice(TEST_EVENTHUB_ID);
2928 std::string dumpStr, eventHubDevStr;
2929 device.dump(dumpStr, eventHubDevStr);
2930}
2931
Prabir Pradhanb54ffb22022-10-27 18:03:34 +00002932TEST_F(InputDeviceTest, GetBluetoothAddress) {
2933 const auto& address = mReader->getBluetoothAddress(DEVICE_ID);
2934 ASSERT_TRUE(address);
2935 ASSERT_EQ(DEVICE_BLUETOOTH_ADDRESS, *address);
2936}
2937
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002938TEST_F(InputDeviceTest, KernelBufferOverflowResetsMappers) {
2939 mFakePolicy->clearViewports();
2940 FakeInputMapper& mapper =
2941 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2942 AINPUT_SOURCE_KEYBOARD);
2943 std::list<NotifyArgs> unused =
2944 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2945 /*changes=*/{});
2946
2947 mapper.assertConfigureWasCalled();
2948 mapper.assertResetWasNotCalled();
2949
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -08002950 RawEvent event{.when = ARBITRARY_TIME,
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002951 .readTime = ARBITRARY_TIME,
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -08002952 .deviceId = EVENTHUB_ID,
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002953 .type = EV_SYN,
2954 .code = SYN_REPORT,
2955 .value = 0};
2956
2957 // Events are processed normally.
2958 unused = mDevice->process(&event, /*count=*/1);
2959 mapper.assertProcessWasCalled();
2960
2961 // Simulate a kernel buffer overflow, which generates a SYN_DROPPED event.
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002962 event.type = EV_SYN;
2963 event.code = SYN_DROPPED;
2964 event.value = 0;
2965 unused = mDevice->process(&event, /*count=*/1);
2966 mapper.assertProcessWasNotCalled();
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002967
2968 // All events until the next SYN_REPORT should be dropped.
2969 event.type = EV_KEY;
2970 event.code = KEY_A;
2971 event.value = 1;
2972 unused = mDevice->process(&event, /*count=*/1);
2973 mapper.assertProcessWasNotCalled();
2974
2975 // We get the SYN_REPORT event now, which is not forwarded to mappers.
Arpit Singh4b4a4572023-11-24 18:19:56 +00002976 // This should reset the mapper.
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002977 event.type = EV_SYN;
2978 event.code = SYN_REPORT;
2979 event.value = 0;
2980 unused = mDevice->process(&event, /*count=*/1);
2981 mapper.assertProcessWasNotCalled();
Arpit Singh4b4a4572023-11-24 18:19:56 +00002982 mapper.assertResetWasCalled();
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002983
2984 // The mapper receives events normally now.
2985 event.type = EV_KEY;
2986 event.code = KEY_B;
2987 event.value = 1;
2988 unused = mDevice->process(&event, /*count=*/1);
2989 mapper.assertProcessWasCalled();
2990}
2991
Michael Wrightd02c5b62014-02-10 15:10:22 -08002992// --- SwitchInputMapperTest ---
2993
2994class SwitchInputMapperTest : public InputMapperTest {
2995protected:
2996};
2997
2998TEST_F(SwitchInputMapperTest, GetSources) {
Arpit Singhdf992eb2023-04-26 16:12:10 +00002999 SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08003000
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003001 ASSERT_EQ(uint32_t(AINPUT_SOURCE_SWITCH), mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003002}
3003
3004TEST_F(SwitchInputMapperTest, GetSwitchState) {
Arpit Singhdf992eb2023-04-26 16:12:10 +00003005 SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08003006
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003007 mFakeEventHub->setSwitchState(EVENTHUB_ID, SW_LID, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003008 ASSERT_EQ(1, mapper.getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003009
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003010 mFakeEventHub->setSwitchState(EVENTHUB_ID, SW_LID, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003011 ASSERT_EQ(0, mapper.getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003012}
3013
3014TEST_F(SwitchInputMapperTest, Process) {
Arpit Singhdf992eb2023-04-26 16:12:10 +00003015 SwitchInputMapper& mapper = constructAndAddMapper<SwitchInputMapper>();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003016 std::list<NotifyArgs> out;
3017 out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SW, SW_LID, 1);
3018 ASSERT_TRUE(out.empty());
3019 out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SW, SW_JACK_PHYSICAL_INSERT, 1);
3020 ASSERT_TRUE(out.empty());
3021 out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SW, SW_HEADPHONE_INSERT, 0);
3022 ASSERT_TRUE(out.empty());
3023 out = process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003024
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003025 ASSERT_EQ(1u, out.size());
3026 const NotifySwitchArgs& args = std::get<NotifySwitchArgs>(*out.begin());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003027 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
Dan Albert1bd2fc02016-02-02 15:11:57 -08003028 ASSERT_EQ((1U << SW_LID) | (1U << SW_JACK_PHYSICAL_INSERT), args.switchValues);
3029 ASSERT_EQ((1U << SW_LID) | (1U << SW_JACK_PHYSICAL_INSERT) | (1 << SW_HEADPHONE_INSERT),
Michael Wrightd02c5b62014-02-10 15:10:22 -08003030 args.switchMask);
3031 ASSERT_EQ(uint32_t(0), args.policyFlags);
3032}
3033
Chris Ye87143712020-11-10 05:05:58 +00003034// --- VibratorInputMapperTest ---
3035class VibratorInputMapperTest : public InputMapperTest {
3036protected:
3037 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::VIBRATOR); }
3038};
3039
3040TEST_F(VibratorInputMapperTest, GetSources) {
Arpit Singh0f26b302023-04-26 16:23:13 +00003041 VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
Chris Ye87143712020-11-10 05:05:58 +00003042
3043 ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mapper.getSources());
3044}
3045
3046TEST_F(VibratorInputMapperTest, GetVibratorIds) {
Arpit Singh0f26b302023-04-26 16:23:13 +00003047 VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
Chris Ye87143712020-11-10 05:05:58 +00003048
3049 ASSERT_EQ(mapper.getVibratorIds().size(), 2U);
3050}
3051
3052TEST_F(VibratorInputMapperTest, Vibrate) {
3053 constexpr uint8_t DEFAULT_AMPLITUDE = 192;
Chris Yefb552902021-02-03 17:18:37 -08003054 constexpr int32_t VIBRATION_TOKEN = 100;
Arpit Singh0f26b302023-04-26 16:23:13 +00003055 VibratorInputMapper& mapper = constructAndAddMapper<VibratorInputMapper>();
Chris Ye87143712020-11-10 05:05:58 +00003056
3057 VibrationElement pattern(2);
3058 VibrationSequence sequence(2);
3059 pattern.duration = std::chrono::milliseconds(200);
Harry Cutts33476232023-01-30 19:57:29 +00003060 pattern.channels = {{/*vibratorId=*/0, DEFAULT_AMPLITUDE / 2},
3061 {/*vibratorId=*/1, DEFAULT_AMPLITUDE}};
Chris Ye87143712020-11-10 05:05:58 +00003062 sequence.addElement(pattern);
3063 pattern.duration = std::chrono::milliseconds(500);
Harry Cutts33476232023-01-30 19:57:29 +00003064 pattern.channels = {{/*vibratorId=*/0, DEFAULT_AMPLITUDE / 4},
3065 {/*vibratorId=*/1, DEFAULT_AMPLITUDE}};
Chris Ye87143712020-11-10 05:05:58 +00003066 sequence.addElement(pattern);
3067
3068 std::vector<int64_t> timings = {0, 1};
3069 std::vector<uint8_t> amplitudes = {DEFAULT_AMPLITUDE, DEFAULT_AMPLITUDE / 2};
3070
3071 ASSERT_FALSE(mapper.isVibrating());
Chris Yefb552902021-02-03 17:18:37 -08003072 // Start vibrating
Harry Cutts33476232023-01-30 19:57:29 +00003073 std::list<NotifyArgs> out = mapper.vibrate(sequence, /*repeat=*/-1, VIBRATION_TOKEN);
Chris Ye87143712020-11-10 05:05:58 +00003074 ASSERT_TRUE(mapper.isVibrating());
Chris Yefb552902021-02-03 17:18:37 -08003075 // Verify vibrator state listener was notified.
3076 mReader->loopOnce();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003077 ASSERT_EQ(1u, out.size());
3078 const NotifyVibratorStateArgs& vibrateArgs = std::get<NotifyVibratorStateArgs>(*out.begin());
3079 ASSERT_EQ(DEVICE_ID, vibrateArgs.deviceId);
3080 ASSERT_TRUE(vibrateArgs.isOn);
Chris Yefb552902021-02-03 17:18:37 -08003081 // Stop vibrating
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003082 out = mapper.cancelVibrate(VIBRATION_TOKEN);
Chris Yefb552902021-02-03 17:18:37 -08003083 ASSERT_FALSE(mapper.isVibrating());
3084 // Verify vibrator state listener was notified.
3085 mReader->loopOnce();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003086 ASSERT_EQ(1u, out.size());
3087 const NotifyVibratorStateArgs& cancelArgs = std::get<NotifyVibratorStateArgs>(*out.begin());
3088 ASSERT_EQ(DEVICE_ID, cancelArgs.deviceId);
3089 ASSERT_FALSE(cancelArgs.isOn);
Chris Ye87143712020-11-10 05:05:58 +00003090}
Michael Wrightd02c5b62014-02-10 15:10:22 -08003091
Chris Yef59a2f42020-10-16 12:55:26 -07003092// --- SensorInputMapperTest ---
3093
3094class SensorInputMapperTest : public InputMapperTest {
3095protected:
3096 static const int32_t ACCEL_RAW_MIN;
3097 static const int32_t ACCEL_RAW_MAX;
3098 static const int32_t ACCEL_RAW_FUZZ;
3099 static const int32_t ACCEL_RAW_FLAT;
3100 static const int32_t ACCEL_RAW_RESOLUTION;
3101
3102 static const int32_t GYRO_RAW_MIN;
3103 static const int32_t GYRO_RAW_MAX;
3104 static const int32_t GYRO_RAW_FUZZ;
3105 static const int32_t GYRO_RAW_FLAT;
3106 static const int32_t GYRO_RAW_RESOLUTION;
3107
3108 static const float GRAVITY_MS2_UNIT;
3109 static const float DEGREE_RADIAN_UNIT;
3110
3111 void prepareAccelAxes();
3112 void prepareGyroAxes();
3113 void setAccelProperties();
3114 void setGyroProperties();
3115 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::SENSOR); }
3116};
3117
3118const int32_t SensorInputMapperTest::ACCEL_RAW_MIN = -32768;
3119const int32_t SensorInputMapperTest::ACCEL_RAW_MAX = 32768;
3120const int32_t SensorInputMapperTest::ACCEL_RAW_FUZZ = 16;
3121const int32_t SensorInputMapperTest::ACCEL_RAW_FLAT = 0;
3122const int32_t SensorInputMapperTest::ACCEL_RAW_RESOLUTION = 8192;
3123
3124const int32_t SensorInputMapperTest::GYRO_RAW_MIN = -2097152;
3125const int32_t SensorInputMapperTest::GYRO_RAW_MAX = 2097152;
3126const int32_t SensorInputMapperTest::GYRO_RAW_FUZZ = 16;
3127const int32_t SensorInputMapperTest::GYRO_RAW_FLAT = 0;
3128const int32_t SensorInputMapperTest::GYRO_RAW_RESOLUTION = 1024;
3129
3130const float SensorInputMapperTest::GRAVITY_MS2_UNIT = 9.80665f;
3131const float SensorInputMapperTest::DEGREE_RADIAN_UNIT = 0.0174533f;
3132
3133void SensorInputMapperTest::prepareAccelAxes() {
3134 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3135 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3136 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3137 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3138 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Z, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3139 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3140}
3141
3142void SensorInputMapperTest::prepareGyroAxes() {
3143 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RX, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3144 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3145 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RY, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3146 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3147 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RZ, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3148 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3149}
3150
3151void SensorInputMapperTest::setAccelProperties() {
3152 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 0, InputDeviceSensorType::ACCELEROMETER,
3153 /* sensorDataIndex */ 0);
3154 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 1, InputDeviceSensorType::ACCELEROMETER,
3155 /* sensorDataIndex */ 1);
3156 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 2, InputDeviceSensorType::ACCELEROMETER,
3157 /* sensorDataIndex */ 2);
3158 mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP);
3159 addConfigurationProperty("sensor.accelerometer.reportingMode", "0");
3160 addConfigurationProperty("sensor.accelerometer.maxDelay", "100000");
3161 addConfigurationProperty("sensor.accelerometer.minDelay", "5000");
3162 addConfigurationProperty("sensor.accelerometer.power", "1.5");
3163}
3164
3165void SensorInputMapperTest::setGyroProperties() {
3166 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 3, InputDeviceSensorType::GYROSCOPE,
3167 /* sensorDataIndex */ 0);
3168 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 4, InputDeviceSensorType::GYROSCOPE,
3169 /* sensorDataIndex */ 1);
3170 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 5, InputDeviceSensorType::GYROSCOPE,
3171 /* sensorDataIndex */ 2);
3172 mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP);
3173 addConfigurationProperty("sensor.gyroscope.reportingMode", "0");
3174 addConfigurationProperty("sensor.gyroscope.maxDelay", "100000");
3175 addConfigurationProperty("sensor.gyroscope.minDelay", "5000");
3176 addConfigurationProperty("sensor.gyroscope.power", "0.8");
3177}
3178
3179TEST_F(SensorInputMapperTest, GetSources) {
Arpit Singhfb706c32023-04-26 15:07:55 +00003180 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003181
3182 ASSERT_EQ(static_cast<uint32_t>(AINPUT_SOURCE_SENSOR), mapper.getSources());
3183}
3184
3185TEST_F(SensorInputMapperTest, ProcessAccelerometerSensor) {
3186 setAccelProperties();
3187 prepareAccelAxes();
Arpit Singhfb706c32023-04-26 15:07:55 +00003188 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003189
3190 ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::ACCELEROMETER,
3191 std::chrono::microseconds(10000),
3192 std::chrono::microseconds(0)));
Chris Yee14523a2020-12-19 13:46:00 -08003193 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003194 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, 20000);
3195 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, -20000);
3196 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Z, 40000);
3197 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000);
3198 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Chris Yef59a2f42020-10-16 12:55:26 -07003199
3200 NotifySensorArgs args;
3201 std::vector<float> values = {20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT,
3202 -20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT,
3203 40000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT};
3204
3205 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args));
3206 ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR);
3207 ASSERT_EQ(args.deviceId, DEVICE_ID);
3208 ASSERT_EQ(args.sensorType, InputDeviceSensorType::ACCELEROMETER);
3209 ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH);
3210 ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME);
3211 ASSERT_EQ(args.values, values);
3212 mapper.flushSensor(InputDeviceSensorType::ACCELEROMETER);
3213}
3214
3215TEST_F(SensorInputMapperTest, ProcessGyroscopeSensor) {
3216 setGyroProperties();
3217 prepareGyroAxes();
Arpit Singhfb706c32023-04-26 15:07:55 +00003218 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003219
3220 ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::GYROSCOPE,
3221 std::chrono::microseconds(10000),
3222 std::chrono::microseconds(0)));
Chris Yee14523a2020-12-19 13:46:00 -08003223 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003224 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RX, 20000);
3225 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RY, -20000);
3226 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RZ, 40000);
3227 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000);
3228 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Chris Yef59a2f42020-10-16 12:55:26 -07003229
3230 NotifySensorArgs args;
3231 std::vector<float> values = {20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT,
3232 -20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT,
3233 40000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT};
3234
3235 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args));
3236 ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR);
3237 ASSERT_EQ(args.deviceId, DEVICE_ID);
3238 ASSERT_EQ(args.sensorType, InputDeviceSensorType::GYROSCOPE);
3239 ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH);
3240 ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME);
3241 ASSERT_EQ(args.values, values);
3242 mapper.flushSensor(InputDeviceSensorType::GYROSCOPE);
3243}
3244
Michael Wrightd02c5b62014-02-10 15:10:22 -08003245// --- KeyboardInputMapperTest ---
3246
3247class KeyboardInputMapperTest : public InputMapperTest {
3248protected:
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003249 const std::string UNIQUE_ID = "local:0";
Zixuan Qufecb6062022-11-12 04:44:31 +00003250 const KeyboardLayoutInfo DEVICE_KEYBOARD_LAYOUT_INFO = KeyboardLayoutInfo("en-US", "qwerty");
Michael Wrighta9cf4192022-12-01 23:46:39 +00003251 void prepareDisplay(ui::Rotation orientation);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003252
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003253 void testDPadKeyRotation(KeyboardInputMapper& mapper, int32_t originalScanCode,
Arthur Hung2c9a3342019-07-23 14:18:59 +08003254 int32_t originalKeyCode, int32_t rotatedKeyCode,
3255 int32_t displayId = ADISPLAY_ID_NONE);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003256};
3257
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003258/* Similar to setDisplayInfoAndReconfigure, but pre-populates all parameters except for the
3259 * orientation.
3260 */
Michael Wrighta9cf4192022-12-01 23:46:39 +00003261void KeyboardInputMapperTest::prepareDisplay(ui::Rotation orientation) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003262 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
3263 NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003264}
3265
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003266void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper& mapper,
Arthur Hung2c9a3342019-07-23 14:18:59 +08003267 int32_t originalScanCode, int32_t originalKeyCode,
3268 int32_t rotatedKeyCode, int32_t displayId) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003269 NotifyKeyArgs args;
3270
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003271 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003272 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3273 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3274 ASSERT_EQ(originalScanCode, args.scanCode);
3275 ASSERT_EQ(rotatedKeyCode, args.keyCode);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003276 ASSERT_EQ(displayId, args.displayId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003277
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003278 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003279 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3280 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3281 ASSERT_EQ(originalScanCode, args.scanCode);
3282 ASSERT_EQ(rotatedKeyCode, args.keyCode);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003283 ASSERT_EQ(displayId, args.displayId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003284}
3285
Michael Wrightd02c5b62014-02-10 15:10:22 -08003286TEST_F(KeyboardInputMapperTest, GetSources) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003287 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003288 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003289 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003290
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003291 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003292}
3293
3294TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) {
3295 const int32_t USAGE_A = 0x070004;
3296 const int32_t USAGE_UNKNOWN = 0x07ffff;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003297 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3298 mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
Chris Yea52ade12020-08-27 16:49:20 -07003299 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, POLICY_FLAG_WAKE);
3300 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, POLICY_FLAG_WAKE);
3301 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, POLICY_FLAG_WAKE);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003302
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003303 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003304 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003305 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Arthur Hung95f68612022-04-07 14:08:22 +08003306 // Initial metastate is AMETA_NONE.
3307 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003308
3309 // Key down by scan code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003310 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003311 NotifyKeyArgs args;
3312 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3313 ASSERT_EQ(DEVICE_ID, args.deviceId);
3314 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3315 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3316 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3317 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3318 ASSERT_EQ(KEY_HOME, args.scanCode);
3319 ASSERT_EQ(AMETA_NONE, args.metaState);
3320 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3321 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3322 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3323
3324 // Key up by scan code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003325 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003326 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3327 ASSERT_EQ(DEVICE_ID, args.deviceId);
3328 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3329 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3330 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3331 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3332 ASSERT_EQ(KEY_HOME, args.scanCode);
3333 ASSERT_EQ(AMETA_NONE, args.metaState);
3334 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3335 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3336 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3337
3338 // Key down by usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003339 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A);
3340 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, 0, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003341 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3342 ASSERT_EQ(DEVICE_ID, args.deviceId);
3343 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3344 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3345 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3346 ASSERT_EQ(AKEYCODE_A, args.keyCode);
3347 ASSERT_EQ(0, args.scanCode);
3348 ASSERT_EQ(AMETA_NONE, args.metaState);
3349 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3350 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3351 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3352
3353 // Key up by usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003354 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A);
3355 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003356 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3357 ASSERT_EQ(DEVICE_ID, args.deviceId);
3358 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3359 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3360 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3361 ASSERT_EQ(AKEYCODE_A, args.keyCode);
3362 ASSERT_EQ(0, args.scanCode);
3363 ASSERT_EQ(AMETA_NONE, args.metaState);
3364 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3365 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3366 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3367
3368 // Key down with unknown scan code or usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003369 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
3370 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003371 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3372 ASSERT_EQ(DEVICE_ID, args.deviceId);
3373 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3374 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3375 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3376 ASSERT_EQ(0, args.keyCode);
3377 ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
3378 ASSERT_EQ(AMETA_NONE, args.metaState);
3379 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3380 ASSERT_EQ(0U, args.policyFlags);
3381 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3382
3383 // Key up with unknown scan code or usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003384 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
3385 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_UNKNOWN, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003386 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3387 ASSERT_EQ(DEVICE_ID, args.deviceId);
3388 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3389 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3390 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3391 ASSERT_EQ(0, args.keyCode);
3392 ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
3393 ASSERT_EQ(AMETA_NONE, args.metaState);
3394 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3395 ASSERT_EQ(0U, args.policyFlags);
3396 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3397}
3398
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003399TEST_F(KeyboardInputMapperTest, Process_KeyRemapping) {
3400 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
3401 mFakeEventHub->addKey(EVENTHUB_ID, KEY_B, 0, AKEYCODE_B, 0);
3402 mFakeEventHub->addKeyRemapping(EVENTHUB_ID, AKEYCODE_A, AKEYCODE_B);
3403
3404 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003405 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003406 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
3407
3408 // Key down by scan code.
3409 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_A, 1);
3410 NotifyKeyArgs args;
3411 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3412 ASSERT_EQ(AKEYCODE_B, args.keyCode);
3413
3414 // Key up by scan code.
3415 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 0);
3416 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3417 ASSERT_EQ(AKEYCODE_B, args.keyCode);
3418}
3419
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003420/**
3421 * Ensure that the readTime is set to the time when the EV_KEY is received.
3422 */
3423TEST_F(KeyboardInputMapperTest, Process_SendsReadTime) {
3424 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3425
3426 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003427 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003428 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
3429 NotifyKeyArgs args;
3430
3431 // Key down
Harry Cutts33476232023-01-30 19:57:29 +00003432 process(mapper, ARBITRARY_TIME, /*readTime=*/12, EV_KEY, KEY_HOME, 1);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003433 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3434 ASSERT_EQ(12, args.readTime);
3435
3436 // Key up
Harry Cutts33476232023-01-30 19:57:29 +00003437 process(mapper, ARBITRARY_TIME, /*readTime=*/15, EV_KEY, KEY_HOME, 1);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003438 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3439 ASSERT_EQ(15, args.readTime);
3440}
3441
Michael Wrightd02c5b62014-02-10 15:10:22 -08003442TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003443 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFTSHIFT, 0, AKEYCODE_SHIFT_LEFT, 0);
3444 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
Chris Yea52ade12020-08-27 16:49:20 -07003445 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 0);
3446 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0);
3447 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003448
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003449 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003450 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003451 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003452
Arthur Hung95f68612022-04-07 14:08:22 +08003453 // Initial metastate is AMETA_NONE.
3454 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003455
3456 // Metakey down.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003457 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003458 NotifyKeyArgs args;
3459 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3460 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003461 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
arthurhungdcef2dc2020-08-11 14:47:50 +08003462 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003463
3464 // Key down.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003465 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003466 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3467 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003468 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003469
3470 // Key up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003471 process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_KEY, KEY_A, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003472 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3473 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003474 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003475
3476 // Metakey up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003477 process(mapper, ARBITRARY_TIME + 3, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003478 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3479 ASSERT_EQ(AMETA_NONE, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003480 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
arthurhungdcef2dc2020-08-11 14:47:50 +08003481 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003482}
3483
3484TEST_F(KeyboardInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateDPad) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003485 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3486 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3487 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3488 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003489
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003490 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003491 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003492 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003493
Michael Wrighta9cf4192022-12-01 23:46:39 +00003494 prepareDisplay(ui::ROTATION_90);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003495 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3496 KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
3497 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3498 KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
3499 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3500 KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
3501 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3502 KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
3503}
3504
3505TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003506 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3507 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3508 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3509 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003510
Michael Wrightd02c5b62014-02-10 15:10:22 -08003511 addConfigurationProperty("keyboard.orientationAware", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003512 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003513 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003514 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003515
Michael Wrighta9cf4192022-12-01 23:46:39 +00003516 prepareDisplay(ui::ROTATION_0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003517 ASSERT_NO_FATAL_FAILURE(
3518 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
3519 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3520 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3521 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3522 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3523 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3524 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003525
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003526 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003527 prepareDisplay(ui::ROTATION_90);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003528 ASSERT_NO_FATAL_FAILURE(
3529 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3530 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3531 AKEYCODE_DPAD_UP, DISPLAY_ID));
3532 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3533 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3534 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3535 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003536
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003537 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003538 prepareDisplay(ui::ROTATION_180);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003539 ASSERT_NO_FATAL_FAILURE(
3540 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3541 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3542 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3543 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3544 AKEYCODE_DPAD_UP, DISPLAY_ID));
3545 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3546 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003547
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003548 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003549 prepareDisplay(ui::ROTATION_270);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003550 ASSERT_NO_FATAL_FAILURE(
3551 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3552 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3553 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3554 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3555 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3556 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3557 AKEYCODE_DPAD_UP, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003558
3559 // Special case: if orientation changes while key is down, we still emit the same keycode
3560 // in the key up as we did in the key down.
3561 NotifyKeyArgs args;
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003562 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003563 prepareDisplay(ui::ROTATION_270);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003564 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003565 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3566 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3567 ASSERT_EQ(KEY_UP, args.scanCode);
3568 ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
3569
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003570 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003571 prepareDisplay(ui::ROTATION_180);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003572 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003573 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3574 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3575 ASSERT_EQ(KEY_UP, args.scanCode);
3576 ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
3577}
3578
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003579TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_NotOrientationAware) {
3580 // If the keyboard is not orientation aware,
3581 // key events should not be associated with a specific display id
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003582 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003583
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003584 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003585 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003586 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003587 NotifyKeyArgs args;
3588
3589 // Display id should be ADISPLAY_ID_NONE without any display configuration.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003590 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003591 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003592 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003593 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3594 ASSERT_EQ(ADISPLAY_ID_NONE, args.displayId);
3595
Michael Wrighta9cf4192022-12-01 23:46:39 +00003596 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003597 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003598 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003599 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003600 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3601 ASSERT_EQ(ADISPLAY_ID_NONE, args.displayId);
3602}
3603
3604TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_OrientationAware) {
3605 // If the keyboard is orientation aware,
3606 // key events should be associated with the internal viewport
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003607 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003608
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003609 addConfigurationProperty("keyboard.orientationAware", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003610 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003611 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003612 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003613 NotifyKeyArgs args;
3614
3615 // Display id should be ADISPLAY_ID_NONE without any display configuration.
3616 // ^--- already checked by the previous test
3617
Michael Wrighta9cf4192022-12-01 23:46:39 +00003618 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003619 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003620 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003621 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003622 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003623 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3624 ASSERT_EQ(DISPLAY_ID, args.displayId);
3625
3626 constexpr int32_t newDisplayId = 2;
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003627 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003628 setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003629 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003630 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003631 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003632 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003633 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3634 ASSERT_EQ(newDisplayId, args.displayId);
3635}
3636
Michael Wrightd02c5b62014-02-10 15:10:22 -08003637TEST_F(KeyboardInputMapperTest, GetKeyCodeState) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003638 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003639 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003640 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003641
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003642 mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003643 ASSERT_EQ(1, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003644
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003645 mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003646 ASSERT_EQ(0, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003647}
3648
Philip Junker4af3b3d2021-12-14 10:36:55 +01003649TEST_F(KeyboardInputMapperTest, GetKeyCodeForKeyLocation) {
3650 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003651 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Philip Junker4af3b3d2021-12-14 10:36:55 +01003652 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
3653
3654 mFakeEventHub->addKeyCodeMapping(EVENTHUB_ID, AKEYCODE_Y, AKEYCODE_Z);
3655 ASSERT_EQ(AKEYCODE_Z, mapper.getKeyCodeForKeyLocation(AKEYCODE_Y))
3656 << "If a mapping is available, the result is equal to the mapping";
3657
3658 ASSERT_EQ(AKEYCODE_A, mapper.getKeyCodeForKeyLocation(AKEYCODE_A))
3659 << "If no mapping is available, the result is the key location";
3660}
3661
Michael Wrightd02c5b62014-02-10 15:10:22 -08003662TEST_F(KeyboardInputMapperTest, GetScanCodeState) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003663 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003664 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003665 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003666
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003667 mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003668 ASSERT_EQ(1, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003669
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003670 mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003671 ASSERT_EQ(0, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003672}
3673
3674TEST_F(KeyboardInputMapperTest, MarkSupportedKeyCodes) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003675 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003676 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003677 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003678
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003679 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003680
Michael Wrightd02c5b62014-02-10 15:10:22 -08003681 uint8_t flags[2] = { 0, 0 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07003682 ASSERT_TRUE(mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_A, AKEYCODE_B}, flags));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003683 ASSERT_TRUE(flags[0]);
3684 ASSERT_FALSE(flags[1]);
3685}
3686
3687TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003688 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3689 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3690 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3691 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3692 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3693 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003694
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003695 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003696 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003697 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Arthur Hung95f68612022-04-07 14:08:22 +08003698 // Initial metastate is AMETA_NONE.
3699 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003700
3701 // Initialization should have turned all of the lights off.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003702 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3703 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3704 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003705
3706 // Toggle caps lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003707 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3708 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003709 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3710 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3711 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003712 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003713
3714 // Toggle num lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003715 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3716 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003717 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3718 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3719 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003720 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003721
3722 // Toggle caps lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003723 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3724 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003725 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3726 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3727 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003728 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003729
3730 // Toggle scroll lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003731 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3732 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003733 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3734 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3735 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003736 ASSERT_EQ(AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003737
3738 // Toggle num lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003739 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3740 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003741 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3742 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3743 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003744 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003745
3746 // Toggle scroll lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003747 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3748 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003749 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3750 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3751 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003752 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003753}
3754
Chris Yea52ade12020-08-27 16:49:20 -07003755TEST_F(KeyboardInputMapperTest, NoMetaStateWhenMetaKeysNotPresent) {
3756 mFakeEventHub->addKey(EVENTHUB_ID, BTN_A, 0, AKEYCODE_BUTTON_A, 0);
3757 mFakeEventHub->addKey(EVENTHUB_ID, BTN_B, 0, AKEYCODE_BUTTON_B, 0);
3758 mFakeEventHub->addKey(EVENTHUB_ID, BTN_X, 0, AKEYCODE_BUTTON_X, 0);
3759 mFakeEventHub->addKey(EVENTHUB_ID, BTN_Y, 0, AKEYCODE_BUTTON_Y, 0);
3760
3761 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003762 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Chris Yea52ade12020-08-27 16:49:20 -07003763 AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC);
3764
Chris Yea52ade12020-08-27 16:49:20 -07003765 // Meta state should be AMETA_NONE after reset
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003766 std::list<NotifyArgs> unused = mapper.reset(ARBITRARY_TIME);
Chris Yea52ade12020-08-27 16:49:20 -07003767 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3768 // Meta state should be AMETA_NONE with update, as device doesn't have the keys.
3769 mapper.updateMetaState(AKEYCODE_NUM_LOCK);
3770 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3771
3772 NotifyKeyArgs args;
3773 // Press button "A"
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003774 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_A, 1);
Chris Yea52ade12020-08-27 16:49:20 -07003775 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3776 ASSERT_EQ(AMETA_NONE, args.metaState);
3777 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3778 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3779 ASSERT_EQ(AKEYCODE_BUTTON_A, args.keyCode);
3780
3781 // Button up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003782 process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_KEY, BTN_A, 0);
Chris Yea52ade12020-08-27 16:49:20 -07003783 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3784 ASSERT_EQ(AMETA_NONE, args.metaState);
3785 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3786 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3787 ASSERT_EQ(AKEYCODE_BUTTON_A, args.keyCode);
3788}
3789
Arthur Hung2c9a3342019-07-23 14:18:59 +08003790TEST_F(KeyboardInputMapperTest, Configure_AssignsDisplayPort) {
3791 // keyboard 1.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003792 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3793 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3794 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3795 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003796
3797 // keyboard 2.
3798 const std::string USB2 = "USB2";
arthurhungdcef2dc2020-08-11 14:47:50 +08003799 const std::string DEVICE_NAME2 = "KEYBOARD2";
Arthur Hung2c9a3342019-07-23 14:18:59 +08003800 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003801 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
arthurhungdcef2dc2020-08-11 14:47:50 +08003802 std::shared_ptr<InputDevice> device2 =
3803 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
Dominik Laskowski2f01d772022-03-23 16:01:29 -07003804 ftl::Flags<InputDeviceClass>(0));
arthurhungdcef2dc2020-08-11 14:47:50 +08003805
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003806 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3807 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3808 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3809 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003810
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003811 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003812 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003813 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003814
Arpit Singh67ca6842023-04-26 14:43:16 +00003815 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003816 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003817 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3818 mFakePolicy
3819 ->getReaderConfiguration(),
3820 AINPUT_SOURCE_KEYBOARD,
3821 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003822 std::list<NotifyArgs> unused =
3823 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003824 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003825 unused += device2->reset(ARBITRARY_TIME);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003826
3827 // Prepared displays and associated info.
3828 constexpr uint8_t hdmi1 = 0;
3829 constexpr uint8_t hdmi2 = 1;
3830 const std::string SECONDARY_UNIQUE_ID = "local:1";
3831
3832 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
3833 mFakePolicy->addInputPortAssociation(USB2, hdmi2);
3834
3835 // No associated display viewport found, should disable the device.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003836 unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003837 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003838 ASSERT_FALSE(device2->isEnabled());
3839
3840 // Prepare second display.
3841 constexpr int32_t newDisplayId = 2;
Michael Wrighta9cf4192022-12-01 23:46:39 +00003842 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003843 UNIQUE_ID, hdmi1, ViewportType::INTERNAL);
Michael Wrighta9cf4192022-12-01 23:46:39 +00003844 setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003845 SECONDARY_UNIQUE_ID, hdmi2, ViewportType::EXTERNAL);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003846 // Default device will reconfigure above, need additional reconfiguration for another device.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003847 unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003848 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003849
3850 // Device should be enabled after the associated display is found.
3851 ASSERT_TRUE(mDevice->isEnabled());
3852 ASSERT_TRUE(device2->isEnabled());
3853
3854 // Test pad key events
3855 ASSERT_NO_FATAL_FAILURE(
3856 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
3857 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3858 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3859 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3860 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3861 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3862 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3863
3864 ASSERT_NO_FATAL_FAILURE(
3865 testDPadKeyRotation(mapper2, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, newDisplayId));
3866 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3867 AKEYCODE_DPAD_RIGHT, newDisplayId));
3868 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3869 AKEYCODE_DPAD_DOWN, newDisplayId));
3870 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3871 AKEYCODE_DPAD_LEFT, newDisplayId));
3872}
Michael Wrightd02c5b62014-02-10 15:10:22 -08003873
arthurhungc903df12020-08-11 15:08:42 +08003874TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleAfterReattach) {
3875 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3876 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3877 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3878 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3879 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3880 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3881
3882 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003883 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
arthurhungc903df12020-08-11 15:08:42 +08003884 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Arthur Hung95f68612022-04-07 14:08:22 +08003885 // Initial metastate is AMETA_NONE.
3886 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
arthurhungc903df12020-08-11 15:08:42 +08003887
3888 // Initialization should have turned all of the lights off.
3889 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3890 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3891 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3892
3893 // Toggle caps lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003894 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3895 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003896 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3897 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
3898
3899 // Toggle num lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003900 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3901 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003902 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3903 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
3904
3905 // Toggle scroll lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003906 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3907 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003908 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3909 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
3910
3911 mFakeEventHub->removeDevice(EVENTHUB_ID);
3912 mReader->loopOnce();
3913
3914 // keyboard 2 should default toggle keys.
3915 const std::string USB2 = "USB2";
3916 const std::string DEVICE_NAME2 = "KEYBOARD2";
3917 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
3918 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
3919 std::shared_ptr<InputDevice> device2 =
3920 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
Dominik Laskowski2f01d772022-03-23 16:01:29 -07003921 ftl::Flags<InputDeviceClass>(0));
arthurhungc903df12020-08-11 15:08:42 +08003922 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3923 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
3924 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3925 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3926 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3927 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3928
Arpit Singh67ca6842023-04-26 14:43:16 +00003929 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
arthurhung6fe95782020-10-05 22:41:16 +08003930 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003931 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3932 mFakePolicy
3933 ->getReaderConfiguration(),
3934 AINPUT_SOURCE_KEYBOARD,
3935 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003936 std::list<NotifyArgs> unused =
3937 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003938 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003939 unused += device2->reset(ARBITRARY_TIME);
arthurhungc903df12020-08-11 15:08:42 +08003940
3941 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_CAPSL));
3942 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_NUML));
3943 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_SCROLLL));
arthurhung6fe95782020-10-05 22:41:16 +08003944 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON,
3945 mapper2.getMetaState());
arthurhungc903df12020-08-11 15:08:42 +08003946}
3947
Arthur Hungcb40a002021-08-03 14:31:01 +00003948TEST_F(KeyboardInputMapperTest, Process_toggleCapsLockState) {
3949 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3950 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3951 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3952
3953 // Suppose we have two mappers. (DPAD + KEYBOARD)
Arpit Singh67ca6842023-04-26 14:43:16 +00003954 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD,
Arthur Hungcb40a002021-08-03 14:31:01 +00003955 AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC);
3956 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00003957 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Arthur Hungcb40a002021-08-03 14:31:01 +00003958 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Arthur Hung95f68612022-04-07 14:08:22 +08003959 // Initial metastate is AMETA_NONE.
3960 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Arthur Hungcb40a002021-08-03 14:31:01 +00003961
3962 mReader->toggleCapsLockState(DEVICE_ID);
3963 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
3964}
3965
Arthur Hungfb3cc112022-04-13 07:39:50 +00003966TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleInMultiDevices) {
3967 // keyboard 1.
3968 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3969 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3970 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3971 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3972 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3973 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3974
3975 KeyboardInputMapper& mapper1 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003976 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Arthur Hungfb3cc112022-04-13 07:39:50 +00003977 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
3978
3979 // keyboard 2.
3980 const std::string USB2 = "USB2";
3981 const std::string DEVICE_NAME2 = "KEYBOARD2";
3982 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
3983 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
3984 std::shared_ptr<InputDevice> device2 =
3985 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
3986 ftl::Flags<InputDeviceClass>(0));
3987 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3988 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
3989 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3990 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3991 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3992 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3993
Arpit Singh67ca6842023-04-26 14:43:16 +00003994 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
Arthur Hungfb3cc112022-04-13 07:39:50 +00003995 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003996 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3997 mFakePolicy
3998 ->getReaderConfiguration(),
3999 AINPUT_SOURCE_KEYBOARD,
4000 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07004001 std::list<NotifyArgs> unused =
4002 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004003 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07004004 unused += device2->reset(ARBITRARY_TIME);
Arthur Hungfb3cc112022-04-13 07:39:50 +00004005
Arthur Hung95f68612022-04-07 14:08:22 +08004006 // Initial metastate is AMETA_NONE.
4007 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
4008 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
4009
4010 // Toggle num lock on and off.
4011 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
4012 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Arthur Hungfb3cc112022-04-13 07:39:50 +00004013 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
4014 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper1.getMetaState());
4015 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper2.getMetaState());
4016
4017 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
4018 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
4019 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
4020 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
4021 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
4022
4023 // Toggle caps lock on and off.
4024 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
4025 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
4026 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
4027 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper1.getMetaState());
4028 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper2.getMetaState());
4029
4030 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
4031 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
4032 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
4033 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
4034 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
4035
4036 // Toggle scroll lock on and off.
4037 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
4038 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
4039 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
4040 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper1.getMetaState());
4041 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper2.getMetaState());
4042
4043 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
4044 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
4045 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
4046 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
4047 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
4048}
4049
Arthur Hung2141d542022-08-23 07:45:21 +00004050TEST_F(KeyboardInputMapperTest, Process_DisabledDevice) {
4051 const int32_t USAGE_A = 0x070004;
4052 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4053 mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
4054
4055 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00004056 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Arthur Hung2141d542022-08-23 07:45:21 +00004057 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
4058 // Key down by scan code.
4059 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
4060 NotifyKeyArgs args;
4061 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4062 ASSERT_EQ(DEVICE_ID, args.deviceId);
4063 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4064 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4065 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
4066 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4067 ASSERT_EQ(KEY_HOME, args.scanCode);
4068 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
4069
4070 // Disable device, it should synthesize cancellation events for down events.
4071 mFakePolicy->addDisabledDevice(DEVICE_ID);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004072 configureDevice(InputReaderConfiguration::Change::ENABLED_STATE);
Arthur Hung2141d542022-08-23 07:45:21 +00004073
4074 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4075 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
4076 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4077 ASSERT_EQ(KEY_HOME, args.scanCode);
4078 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_CANCELED, args.flags);
4079}
4080
Zixuan Qufecb6062022-11-12 04:44:31 +00004081TEST_F(KeyboardInputMapperTest, Configure_AssignKeyboardLayoutInfo) {
Arpit Singh67ca6842023-04-26 14:43:16 +00004082 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
4083 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Zixuan Qufecb6062022-11-12 04:44:31 +00004084 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004085 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
4086 /*changes=*/{});
Zixuan Qufecb6062022-11-12 04:44:31 +00004087
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +00004088 uint32_t generation = mReader->getContext()->getGeneration();
Zixuan Qufecb6062022-11-12 04:44:31 +00004089 mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
4090
4091 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004092 InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
Zixuan Qufecb6062022-11-12 04:44:31 +00004093
4094 InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
4095 ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.languageTag,
4096 deviceInfo.getKeyboardLayoutInfo()->languageTag);
4097 ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.layoutType,
4098 deviceInfo.getKeyboardLayoutInfo()->layoutType);
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +00004099 ASSERT_TRUE(mReader->getContext()->getGeneration() != generation);
4100
4101 // Call change layout association with the same values: Generation shouldn't change
4102 generation = mReader->getContext()->getGeneration();
4103 mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
4104 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
4105 InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
4106 ASSERT_TRUE(mReader->getContext()->getGeneration() == generation);
Zixuan Qufecb6062022-11-12 04:44:31 +00004107}
4108
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004109TEST_F(KeyboardInputMapperTest, LayoutInfoCorrectlyMapped) {
4110 mFakeEventHub->setRawLayoutInfo(EVENTHUB_ID,
4111 RawLayoutInfo{.languageTag = "en", .layoutType = "extended"});
4112
4113 // Configuration
Arpit Singh67ca6842023-04-26 14:43:16 +00004114 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004115 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
4116 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004117 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004118
4119 ASSERT_EQ("en", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->languageTag);
4120 ASSERT_EQ("extended", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->layoutType);
4121}
4122
Justin Chung71ddb432023-03-27 04:29:07 +00004123TEST_F(KeyboardInputMapperTest, Process_GesureEventToSetFlagKeepTouchMode) {
4124 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, POLICY_FLAG_GESTURE);
4125 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00004126 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Justin Chung71ddb432023-03-27 04:29:07 +00004127 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
4128 NotifyKeyArgs args;
4129
4130 // Key down
4131 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFT, 1);
4132 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4133 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_KEEP_TOUCH_MODE, args.flags);
4134}
4135
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004136// --- KeyboardInputMapperTest_ExternalDevice ---
4137
4138class KeyboardInputMapperTest_ExternalDevice : public InputMapperTest {
4139protected:
Chris Yea52ade12020-08-27 16:49:20 -07004140 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL); }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004141};
4142
Vaibhav Devmurari2681a812024-01-11 00:15:35 +00004143TEST_F(KeyboardInputMapperTest_ExternalDevice, WakeBehavior_AlphabeticKeyboard) {
Vaibhav Devmurari16257862023-03-06 10:06:32 +00004144 // For external devices, keys will trigger wake on key down. Media keys should also trigger
4145 // wake if triggered from external devices.
Powei Fengd041c5d2019-05-03 17:11:33 -07004146
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004147 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, 0);
4148 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
4149 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
4150 POLICY_FLAG_WAKE);
Powei Fengd041c5d2019-05-03 17:11:33 -07004151
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004152 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00004153 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004154 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Powei Fengd041c5d2019-05-03 17:11:33 -07004155
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004156 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004157 NotifyKeyArgs args;
4158 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4159 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4160
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004161 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004162 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4163 ASSERT_EQ(uint32_t(0), args.policyFlags);
4164
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004165 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004166 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Vaibhav Devmurari16257862023-03-06 10:06:32 +00004167 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
Powei Fengd041c5d2019-05-03 17:11:33 -07004168
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004169 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004170 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4171 ASSERT_EQ(uint32_t(0), args.policyFlags);
4172
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004173 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004174 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4175 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4176
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004177 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004178 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4179 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4180}
4181
Vaibhav Devmurari2681a812024-01-11 00:15:35 +00004182TEST_F(KeyboardInputMapperTest_ExternalDevice, WakeBehavior_NoneAlphabeticKeyboard) {
4183 // For external devices, keys will trigger wake on key down. Media keys should not trigger
4184 // wake if triggered from external non-alphaebtic keyboard (e.g. headsets).
4185
4186 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
4187 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
4188 POLICY_FLAG_WAKE);
4189
4190 KeyboardInputMapper& mapper =
4191 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
4192 AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC);
4193
4194 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
4195 NotifyKeyArgs args;
4196 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4197 ASSERT_EQ(uint32_t(0), args.policyFlags);
4198
4199 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
4200 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4201 ASSERT_EQ(uint32_t(0), args.policyFlags);
4202
4203 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1);
4204 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4205 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4206
4207 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0);
4208 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4209 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4210}
4211
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004212TEST_F(KeyboardInputMapperTest_ExternalDevice, DoNotWakeByDefaultBehavior) {
Powei Fengd041c5d2019-05-03 17:11:33 -07004213 // Tv Remote key's wake behavior is prescribed by the keylayout file.
Powei Fengd041c5d2019-05-03 17:11:33 -07004214
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004215 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4216 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
4217 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, POLICY_FLAG_WAKE);
Powei Fengd041c5d2019-05-03 17:11:33 -07004218
Powei Fengd041c5d2019-05-03 17:11:33 -07004219 addConfigurationProperty("keyboard.doNotWakeByDefault", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004220 KeyboardInputMapper& mapper =
Arpit Singh67ca6842023-04-26 14:43:16 +00004221 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004222 AINPUT_KEYBOARD_TYPE_ALPHABETIC);
Powei Fengd041c5d2019-05-03 17:11:33 -07004223
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004224 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004225 NotifyKeyArgs args;
4226 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4227 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4228
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004229 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004230 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4231 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4232
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004233 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_DOWN, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004234 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4235 ASSERT_EQ(uint32_t(0), args.policyFlags);
4236
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004237 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_DOWN, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004238 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4239 ASSERT_EQ(uint32_t(0), args.policyFlags);
4240
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004241 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004242 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4243 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4244
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004245 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004246 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4247 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4248}
4249
Michael Wrightd02c5b62014-02-10 15:10:22 -08004250// --- TouchInputMapperTest ---
4251
4252class TouchInputMapperTest : public InputMapperTest {
4253protected:
4254 static const int32_t RAW_X_MIN;
4255 static const int32_t RAW_X_MAX;
4256 static const int32_t RAW_Y_MIN;
4257 static const int32_t RAW_Y_MAX;
4258 static const int32_t RAW_TOUCH_MIN;
4259 static const int32_t RAW_TOUCH_MAX;
4260 static const int32_t RAW_TOOL_MIN;
4261 static const int32_t RAW_TOOL_MAX;
4262 static const int32_t RAW_PRESSURE_MIN;
4263 static const int32_t RAW_PRESSURE_MAX;
4264 static const int32_t RAW_ORIENTATION_MIN;
4265 static const int32_t RAW_ORIENTATION_MAX;
4266 static const int32_t RAW_DISTANCE_MIN;
4267 static const int32_t RAW_DISTANCE_MAX;
4268 static const int32_t RAW_TILT_MIN;
4269 static const int32_t RAW_TILT_MAX;
4270 static const int32_t RAW_ID_MIN;
4271 static const int32_t RAW_ID_MAX;
4272 static const int32_t RAW_SLOT_MIN;
4273 static const int32_t RAW_SLOT_MAX;
4274 static const float X_PRECISION;
4275 static const float Y_PRECISION;
Santos Cordonfa5cf462017-04-05 10:37:00 -07004276 static const float X_PRECISION_VIRTUAL;
4277 static const float Y_PRECISION_VIRTUAL;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004278
4279 static const float GEOMETRIC_SCALE;
Jason Gerecke489fda82012-09-07 17:19:40 -07004280 static const TouchAffineTransformation AFFINE_TRANSFORM;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004281
4282 static const VirtualKeyDefinition VIRTUAL_KEYS[2];
4283
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07004284 const std::string UNIQUE_ID = "local:0";
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004285 const std::string SECONDARY_UNIQUE_ID = "local:1";
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07004286
Michael Wrightd02c5b62014-02-10 15:10:22 -08004287 enum Axes {
4288 POSITION = 1 << 0,
4289 TOUCH = 1 << 1,
4290 TOOL = 1 << 2,
4291 PRESSURE = 1 << 3,
4292 ORIENTATION = 1 << 4,
4293 MINOR = 1 << 5,
4294 ID = 1 << 6,
4295 DISTANCE = 1 << 7,
4296 TILT = 1 << 8,
4297 SLOT = 1 << 9,
4298 TOOL_TYPE = 1 << 10,
4299 };
4300
Michael Wrighta9cf4192022-12-01 23:46:39 +00004301 void prepareDisplay(ui::Rotation orientation, std::optional<uint8_t> port = NO_PORT);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004302 void prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port = NO_PORT);
Michael Wrighta9cf4192022-12-01 23:46:39 +00004303 void prepareVirtualDisplay(ui::Rotation orientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004304 void prepareVirtualKeys();
Jason Gerecke489fda82012-09-07 17:19:40 -07004305 void prepareLocationCalibration();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004306 int32_t toRawX(float displayX);
4307 int32_t toRawY(float displayY);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07004308 int32_t toRotatedRawX(float displayX);
4309 int32_t toRotatedRawY(float displayY);
Jason Gerecke489fda82012-09-07 17:19:40 -07004310 float toCookedX(float rawX, float rawY);
4311 float toCookedY(float rawX, float rawY);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004312 float toDisplayX(int32_t rawX);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004313 float toDisplayX(int32_t rawX, int32_t displayWidth);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004314 float toDisplayY(int32_t rawY);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004315 float toDisplayY(int32_t rawY, int32_t displayHeight);
4316
Michael Wrightd02c5b62014-02-10 15:10:22 -08004317};
4318
4319const int32_t TouchInputMapperTest::RAW_X_MIN = 25;
4320const int32_t TouchInputMapperTest::RAW_X_MAX = 1019;
4321const int32_t TouchInputMapperTest::RAW_Y_MIN = 30;
4322const int32_t TouchInputMapperTest::RAW_Y_MAX = 1009;
4323const int32_t TouchInputMapperTest::RAW_TOUCH_MIN = 0;
4324const int32_t TouchInputMapperTest::RAW_TOUCH_MAX = 31;
4325const int32_t TouchInputMapperTest::RAW_TOOL_MIN = 0;
4326const int32_t TouchInputMapperTest::RAW_TOOL_MAX = 15;
Michael Wrightaa449c92017-12-13 21:21:43 +00004327const int32_t TouchInputMapperTest::RAW_PRESSURE_MIN = 0;
4328const int32_t TouchInputMapperTest::RAW_PRESSURE_MAX = 255;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004329const int32_t TouchInputMapperTest::RAW_ORIENTATION_MIN = -7;
4330const int32_t TouchInputMapperTest::RAW_ORIENTATION_MAX = 7;
4331const int32_t TouchInputMapperTest::RAW_DISTANCE_MIN = 0;
4332const int32_t TouchInputMapperTest::RAW_DISTANCE_MAX = 7;
4333const int32_t TouchInputMapperTest::RAW_TILT_MIN = 0;
4334const int32_t TouchInputMapperTest::RAW_TILT_MAX = 150;
4335const int32_t TouchInputMapperTest::RAW_ID_MIN = 0;
4336const int32_t TouchInputMapperTest::RAW_ID_MAX = 9;
4337const int32_t TouchInputMapperTest::RAW_SLOT_MIN = 0;
4338const int32_t TouchInputMapperTest::RAW_SLOT_MAX = 9;
4339const float TouchInputMapperTest::X_PRECISION = float(RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH;
4340const float TouchInputMapperTest::Y_PRECISION = float(RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT;
Santos Cordonfa5cf462017-04-05 10:37:00 -07004341const float TouchInputMapperTest::X_PRECISION_VIRTUAL =
4342 float(RAW_X_MAX - RAW_X_MIN + 1) / VIRTUAL_DISPLAY_WIDTH;
4343const float TouchInputMapperTest::Y_PRECISION_VIRTUAL =
4344 float(RAW_Y_MAX - RAW_Y_MIN + 1) / VIRTUAL_DISPLAY_HEIGHT;
Jason Gerecke489fda82012-09-07 17:19:40 -07004345const TouchAffineTransformation TouchInputMapperTest::AFFINE_TRANSFORM =
4346 TouchAffineTransformation(1, -2, 3, -4, 5, -6);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004347
4348const float TouchInputMapperTest::GEOMETRIC_SCALE =
4349 avg(float(DISPLAY_WIDTH) / (RAW_X_MAX - RAW_X_MIN + 1),
4350 float(DISPLAY_HEIGHT) / (RAW_Y_MAX - RAW_Y_MIN + 1));
4351
4352const VirtualKeyDefinition TouchInputMapperTest::VIRTUAL_KEYS[2] = {
4353 { KEY_HOME, 60, DISPLAY_HEIGHT + 15, 20, 20 },
4354 { KEY_MENU, DISPLAY_HEIGHT - 60, DISPLAY_WIDTH + 15, 20, 20 },
4355};
4356
Michael Wrighta9cf4192022-12-01 23:46:39 +00004357void TouchInputMapperTest::prepareDisplay(ui::Rotation orientation, std::optional<uint8_t> port) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01004358 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
4359 port, ViewportType::INTERNAL);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004360}
4361
4362void TouchInputMapperTest::prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port) {
4363 setDisplayInfoAndReconfigure(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00004364 ui::ROTATION_0, SECONDARY_UNIQUE_ID, port, type);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004365}
4366
Michael Wrighta9cf4192022-12-01 23:46:39 +00004367void TouchInputMapperTest::prepareVirtualDisplay(ui::Rotation orientation) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01004368 setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH, VIRTUAL_DISPLAY_HEIGHT,
4369 orientation, VIRTUAL_DISPLAY_UNIQUE_ID, NO_PORT,
4370 ViewportType::VIRTUAL);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004371}
4372
Michael Wrightd02c5b62014-02-10 15:10:22 -08004373void TouchInputMapperTest::prepareVirtualKeys() {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004374 mFakeEventHub->addVirtualKeyDefinition(EVENTHUB_ID, VIRTUAL_KEYS[0]);
4375 mFakeEventHub->addVirtualKeyDefinition(EVENTHUB_ID, VIRTUAL_KEYS[1]);
4376 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4377 mFakeEventHub->addKey(EVENTHUB_ID, KEY_MENU, 0, AKEYCODE_MENU, POLICY_FLAG_WAKE);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004378}
4379
Jason Gerecke489fda82012-09-07 17:19:40 -07004380void TouchInputMapperTest::prepareLocationCalibration() {
4381 mFakePolicy->setTouchAffineTransformation(AFFINE_TRANSFORM);
4382}
4383
Michael Wrightd02c5b62014-02-10 15:10:22 -08004384int32_t TouchInputMapperTest::toRawX(float displayX) {
4385 return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH + RAW_X_MIN);
4386}
4387
4388int32_t TouchInputMapperTest::toRawY(float displayY) {
4389 return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT + RAW_Y_MIN);
4390}
4391
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07004392int32_t TouchInputMapperTest::toRotatedRawX(float displayX) {
4393 return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_HEIGHT + RAW_X_MIN);
4394}
4395
4396int32_t TouchInputMapperTest::toRotatedRawY(float displayY) {
4397 return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_WIDTH + RAW_Y_MIN);
4398}
4399
Jason Gerecke489fda82012-09-07 17:19:40 -07004400float TouchInputMapperTest::toCookedX(float rawX, float rawY) {
4401 AFFINE_TRANSFORM.applyTo(rawX, rawY);
4402 return rawX;
4403}
4404
4405float TouchInputMapperTest::toCookedY(float rawX, float rawY) {
4406 AFFINE_TRANSFORM.applyTo(rawX, rawY);
4407 return rawY;
4408}
4409
Michael Wrightd02c5b62014-02-10 15:10:22 -08004410float TouchInputMapperTest::toDisplayX(int32_t rawX) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004411 return toDisplayX(rawX, DISPLAY_WIDTH);
4412}
4413
4414float TouchInputMapperTest::toDisplayX(int32_t rawX, int32_t displayWidth) {
4415 return float(rawX - RAW_X_MIN) * displayWidth / (RAW_X_MAX - RAW_X_MIN + 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004416}
4417
4418float TouchInputMapperTest::toDisplayY(int32_t rawY) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004419 return toDisplayY(rawY, DISPLAY_HEIGHT);
4420}
4421
4422float TouchInputMapperTest::toDisplayY(int32_t rawY, int32_t displayHeight) {
4423 return float(rawY - RAW_Y_MIN) * displayHeight / (RAW_Y_MAX - RAW_Y_MIN + 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004424}
4425
4426
4427// --- SingleTouchInputMapperTest ---
4428
4429class SingleTouchInputMapperTest : public TouchInputMapperTest {
4430protected:
4431 void prepareButtons();
4432 void prepareAxes(int axes);
4433
Biswarup Palb08159b2024-08-22 09:12:19 +00004434 std::list<NotifyArgs> processDown(SingleTouchInputMapper& mapper, int32_t x, int32_t y);
4435 std::list<NotifyArgs> processMove(SingleTouchInputMapper& mapper, int32_t x, int32_t y);
4436 std::list<NotifyArgs> processUp(SingleTouchInputMapper& mappery);
4437 std::list<NotifyArgs> processPressure(SingleTouchInputMapper& mapper, int32_t pressure);
4438 std::list<NotifyArgs> processToolMajor(SingleTouchInputMapper& mapper, int32_t toolMajor);
4439 std::list<NotifyArgs> processDistance(SingleTouchInputMapper& mapper, int32_t distance);
4440 std::list<NotifyArgs> processTilt(SingleTouchInputMapper& mapper, int32_t tiltX, int32_t tiltY);
4441 std::list<NotifyArgs> processKey(SingleTouchInputMapper& mapper, int32_t code, int32_t value);
4442 std::list<NotifyArgs> processSync(SingleTouchInputMapper& mapper);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004443};
4444
4445void SingleTouchInputMapperTest::prepareButtons() {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004446 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004447}
4448
4449void SingleTouchInputMapperTest::prepareAxes(int axes) {
4450 if (axes & POSITION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004451 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
4452 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004453 }
4454 if (axes & PRESSURE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004455 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_PRESSURE, RAW_PRESSURE_MIN,
4456 RAW_PRESSURE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004457 }
4458 if (axes & TOOL) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004459 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TOOL_WIDTH, RAW_TOOL_MIN, RAW_TOOL_MAX, 0,
4460 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004461 }
4462 if (axes & DISTANCE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004463 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_DISTANCE, RAW_DISTANCE_MIN,
4464 RAW_DISTANCE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004465 }
4466 if (axes & TILT) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004467 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TILT_X, RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
4468 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TILT_Y, RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004469 }
4470}
4471
Biswarup Palb08159b2024-08-22 09:12:19 +00004472std::list<NotifyArgs> SingleTouchInputMapperTest::processDown(SingleTouchInputMapper& mapper,
4473 int32_t x, int32_t y) {
4474 std::list<NotifyArgs> args;
4475 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
4476 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, x);
4477 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, y);
4478 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004479}
4480
Biswarup Palb08159b2024-08-22 09:12:19 +00004481std::list<NotifyArgs> SingleTouchInputMapperTest::processMove(SingleTouchInputMapper& mapper,
4482 int32_t x, int32_t y) {
4483 std::list<NotifyArgs> args;
4484 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, x);
4485 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, y);
4486 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004487}
4488
Biswarup Palb08159b2024-08-22 09:12:19 +00004489std::list<NotifyArgs> SingleTouchInputMapperTest::processUp(SingleTouchInputMapper& mapper) {
4490 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004491}
4492
Biswarup Palb08159b2024-08-22 09:12:19 +00004493std::list<NotifyArgs> SingleTouchInputMapperTest::processPressure(SingleTouchInputMapper& mapper,
4494 int32_t pressure) {
4495 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_PRESSURE, pressure);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004496}
4497
Biswarup Palb08159b2024-08-22 09:12:19 +00004498std::list<NotifyArgs> SingleTouchInputMapperTest::processToolMajor(SingleTouchInputMapper& mapper,
4499 int32_t toolMajor) {
4500 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TOOL_WIDTH, toolMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004501}
4502
Biswarup Palb08159b2024-08-22 09:12:19 +00004503std::list<NotifyArgs> SingleTouchInputMapperTest::processDistance(SingleTouchInputMapper& mapper,
4504 int32_t distance) {
4505 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_DISTANCE, distance);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004506}
4507
Biswarup Palb08159b2024-08-22 09:12:19 +00004508std::list<NotifyArgs> SingleTouchInputMapperTest::processTilt(SingleTouchInputMapper& mapper,
4509 int32_t tiltX, int32_t tiltY) {
4510 std::list<NotifyArgs> args;
4511 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TILT_X, tiltX);
4512 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TILT_Y, tiltY);
4513 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004514}
4515
Biswarup Palb08159b2024-08-22 09:12:19 +00004516std::list<NotifyArgs> SingleTouchInputMapperTest::processKey(SingleTouchInputMapper& mapper,
4517 int32_t code, int32_t value) {
4518 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004519}
4520
Biswarup Palb08159b2024-08-22 09:12:19 +00004521std::list<NotifyArgs> SingleTouchInputMapperTest::processSync(SingleTouchInputMapper& mapper) {
4522 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004523}
4524
Michael Wrightd02c5b62014-02-10 15:10:22 -08004525TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndNotACursor_ReturnsPointer) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004526 prepareButtons();
4527 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00004528 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004529
Josep del Río2d8c79a2023-01-23 19:33:50 +00004530 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004531}
4532
Michael Wrightd02c5b62014-02-10 15:10:22 -08004533TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004534 prepareButtons();
4535 prepareAxes(POSITION);
4536 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00004537 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004538
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004539 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004540}
4541
4542TEST_F(SingleTouchInputMapperTest, GetKeyCodeState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004543 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004544 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004545 prepareButtons();
4546 prepareAxes(POSITION);
4547 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004548 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004549
4550 // Unknown key.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004551 ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004552
4553 // Virtual key is down.
4554 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4555 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4556 processDown(mapper, x, y);
4557 processSync(mapper);
4558 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4559
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004560 ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004561
4562 // Virtual key is up.
4563 processUp(mapper);
4564 processSync(mapper);
4565 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4566
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004567 ASSERT_EQ(AKEY_STATE_UP, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004568}
4569
4570TEST_F(SingleTouchInputMapperTest, GetScanCodeState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004571 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004572 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004573 prepareButtons();
4574 prepareAxes(POSITION);
4575 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004576 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004577
4578 // Unknown key.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004579 ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004580
4581 // Virtual key is down.
4582 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4583 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4584 processDown(mapper, x, y);
4585 processSync(mapper);
4586 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4587
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004588 ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004589
4590 // Virtual key is up.
4591 processUp(mapper);
4592 processSync(mapper);
4593 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4594
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004595 ASSERT_EQ(AKEY_STATE_UP, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004596}
4597
4598TEST_F(SingleTouchInputMapperTest, MarkSupportedKeyCodes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004599 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004600 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004601 prepareButtons();
4602 prepareAxes(POSITION);
4603 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004604 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004605
Michael Wrightd02c5b62014-02-10 15:10:22 -08004606 uint8_t flags[2] = { 0, 0 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07004607 ASSERT_TRUE(
4608 mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_HOME, AKEYCODE_A}, flags));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004609 ASSERT_TRUE(flags[0]);
4610 ASSERT_FALSE(flags[1]);
4611}
4612
Biswarup Palb08159b2024-08-22 09:12:19 +00004613TEST_F(SingleTouchInputMapperTest, DeviceTypeChange_RecalculatesRawToDisplayTransform) {
4614 prepareDisplay(ui::ROTATION_0);
4615 prepareAxes(POSITION);
4616 addConfigurationProperty("touch.deviceType", "touchScreen");
4617 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
4618
4619 const int32_t x = 900;
4620 const int32_t y = 75;
4621 std::list<NotifyArgs> args;
4622 args += processDown(mapper, x, y);
4623 args += processSync(mapper);
4624
4625 // Assert that motion event is received in display coordinate space for deviceType touchScreen.
4626 ASSERT_THAT(args,
4627 ElementsAre(VariantWith<NotifyMotionArgs>(
4628 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4629 WithCoords(toDisplayX(x), toDisplayY(y))))));
4630
4631 // Add device type association after the device was created.
4632 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
4633 // Send update to the mapper.
4634 std::list<NotifyArgs> unused =
4635 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
4636 InputReaderConfiguration::Change::DEVICE_TYPE /*changes*/);
4637
4638 args.clear();
4639 args += processDown(mapper, x, y);
4640 args += processSync(mapper);
4641
4642 // Assert that motion event is received in raw coordinate space for deviceType touchNavigation.
4643 ASSERT_THAT(args,
4644 ElementsAre(VariantWith<NotifyMotionArgs>(
4645 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4646 WithCoords(x - RAW_X_MIN, y - RAW_Y_MIN)))));
4647}
4648
Michael Wrightd02c5b62014-02-10 15:10:22 -08004649TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNormally_SendsKeyDownAndKeyUp) {
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
arthurhungdcef2dc2020-08-11 14:47:50 +08004657 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004658
4659 NotifyKeyArgs args;
4660
4661 // Press virtual key.
4662 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4663 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4664 processDown(mapper, x, y);
4665 processSync(mapper);
4666
4667 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4668 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4669 ASSERT_EQ(DEVICE_ID, args.deviceId);
4670 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4671 ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
4672 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
4673 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
4674 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4675 ASSERT_EQ(KEY_HOME, args.scanCode);
4676 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
4677 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
4678
4679 // Release virtual key.
4680 processUp(mapper);
4681 processSync(mapper);
4682
4683 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4684 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4685 ASSERT_EQ(DEVICE_ID, args.deviceId);
4686 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4687 ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
4688 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
4689 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
4690 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4691 ASSERT_EQ(KEY_HOME, args.scanCode);
4692 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
4693 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
4694
4695 // Should not have sent any motions.
4696 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4697}
4698
4699TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfBounds_SendsKeyDownAndKeyCancel) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004700 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004701 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004702 prepareButtons();
4703 prepareAxes(POSITION);
4704 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004705 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004706
arthurhungdcef2dc2020-08-11 14:47:50 +08004707 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004708
4709 NotifyKeyArgs keyArgs;
4710
4711 // Press virtual key.
4712 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4713 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4714 processDown(mapper, x, y);
4715 processSync(mapper);
4716
4717 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
4718 ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
4719 ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
4720 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
4721 ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
4722 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
4723 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, keyArgs.flags);
4724 ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
4725 ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
4726 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
4727 ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
4728
4729 // Move out of bounds. This should generate a cancel and a pointer down since we moved
4730 // into the display area.
4731 y -= 100;
4732 processMove(mapper, x, y);
4733 processSync(mapper);
4734
4735 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
4736 ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
4737 ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
4738 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
4739 ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
4740 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
4741 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
4742 | AKEY_EVENT_FLAG_CANCELED, keyArgs.flags);
4743 ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
4744 ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
4745 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
4746 ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
4747
4748 NotifyMotionArgs motionArgs;
4749 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4750 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4751 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4752 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4753 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4754 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4755 ASSERT_EQ(0, motionArgs.flags);
4756 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4757 ASSERT_EQ(0, motionArgs.buttonState);
4758 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004759 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004760 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004761 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004762 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4763 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4764 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4765 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4766 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4767
4768 // Keep moving out of bounds. Should generate a pointer move.
4769 y -= 50;
4770 processMove(mapper, x, y);
4771 processSync(mapper);
4772
4773 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4774 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4775 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4776 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4777 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4778 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
4779 ASSERT_EQ(0, motionArgs.flags);
4780 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4781 ASSERT_EQ(0, motionArgs.buttonState);
4782 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004783 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004784 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004785 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004786 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4787 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4788 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4789 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4790 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4791
4792 // Release out of bounds. Should generate a pointer up.
4793 processUp(mapper);
4794 processSync(mapper);
4795
4796 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4797 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4798 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4799 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4800 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4801 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4802 ASSERT_EQ(0, motionArgs.flags);
4803 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4804 ASSERT_EQ(0, motionArgs.buttonState);
4805 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004806 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004807 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004808 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004809 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4810 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4811 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4812 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4813 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4814
4815 // Should not have sent any more keys or motions.
4816 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4817 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4818}
4819
4820TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMovesIn_SendsDownAsTouchEntersDisplay) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004821 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004822 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004823 prepareButtons();
4824 prepareAxes(POSITION);
4825 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004826 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004827
arthurhungdcef2dc2020-08-11 14:47:50 +08004828 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004829
4830 NotifyMotionArgs motionArgs;
4831
4832 // Initially go down out of bounds.
4833 int32_t x = -10;
4834 int32_t y = -10;
4835 processDown(mapper, x, y);
4836 processSync(mapper);
4837
4838 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4839
4840 // Move into the display area. Should generate a pointer down.
4841 x = 50;
4842 y = 75;
4843 processMove(mapper, x, y);
4844 processSync(mapper);
4845
4846 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4847 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4848 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4849 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4850 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4851 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4852 ASSERT_EQ(0, motionArgs.flags);
4853 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4854 ASSERT_EQ(0, motionArgs.buttonState);
4855 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004856 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004857 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004858 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004859 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4860 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4861 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4862 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4863 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4864
4865 // Release. Should generate a pointer up.
4866 processUp(mapper);
4867 processSync(mapper);
4868
4869 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4870 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4871 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4872 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4873 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4874 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4875 ASSERT_EQ(0, motionArgs.flags);
4876 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4877 ASSERT_EQ(0, motionArgs.buttonState);
4878 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004879 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004880 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004881 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004882 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4883 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4884 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4885 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4886 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4887
4888 // Should not have sent any more keys or motions.
4889 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4890 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4891}
4892
Santos Cordonfa5cf462017-04-05 10:37:00 -07004893TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture_VirtualDisplay) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004894 addConfigurationProperty("touch.deviceType", "touchScreen");
4895 addConfigurationProperty("touch.displayId", VIRTUAL_DISPLAY_UNIQUE_ID);
4896
Michael Wrighta9cf4192022-12-01 23:46:39 +00004897 prepareVirtualDisplay(ui::ROTATION_0);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004898 prepareButtons();
4899 prepareAxes(POSITION);
4900 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004901 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Santos Cordonfa5cf462017-04-05 10:37:00 -07004902
arthurhungdcef2dc2020-08-11 14:47:50 +08004903 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004904
4905 NotifyMotionArgs motionArgs;
4906
4907 // Down.
4908 int32_t x = 100;
4909 int32_t y = 125;
4910 processDown(mapper, x, y);
4911 processSync(mapper);
4912
4913 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4914 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4915 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4916 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4917 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4918 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4919 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4920 ASSERT_EQ(0, motionArgs.flags);
4921 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4922 ASSERT_EQ(0, motionArgs.buttonState);
4923 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004924 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004925 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004926 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004927 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4928 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4929 1, 0, 0, 0, 0, 0, 0, 0));
4930 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4931 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4932 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4933
4934 // Move.
4935 x += 50;
4936 y += 75;
4937 processMove(mapper, x, y);
4938 processSync(mapper);
4939
4940 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4941 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4942 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4943 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4944 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4945 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4946 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
4947 ASSERT_EQ(0, motionArgs.flags);
4948 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4949 ASSERT_EQ(0, motionArgs.buttonState);
4950 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004951 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004952 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004953 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004954 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4955 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4956 1, 0, 0, 0, 0, 0, 0, 0));
4957 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4958 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4959 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4960
4961 // Up.
4962 processUp(mapper);
4963 processSync(mapper);
4964
4965 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4966 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4967 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4968 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4969 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4970 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4971 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4972 ASSERT_EQ(0, motionArgs.flags);
4973 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4974 ASSERT_EQ(0, motionArgs.buttonState);
4975 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004976 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004977 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004978 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004979 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4980 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4981 1, 0, 0, 0, 0, 0, 0, 0));
4982 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4983 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4984 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4985
4986 // Should not have sent any more keys or motions.
4987 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4988 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4989}
4990
Michael Wrightd02c5b62014-02-10 15:10:22 -08004991TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004992 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004993 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004994 prepareButtons();
4995 prepareAxes(POSITION);
4996 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004997 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004998
arthurhungdcef2dc2020-08-11 14:47:50 +08004999 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005000
5001 NotifyMotionArgs motionArgs;
5002
5003 // Down.
5004 int32_t x = 100;
5005 int32_t y = 125;
5006 processDown(mapper, x, y);
5007 processSync(mapper);
5008
5009 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5010 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5011 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5012 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5013 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5014 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5015 ASSERT_EQ(0, motionArgs.flags);
5016 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5017 ASSERT_EQ(0, motionArgs.buttonState);
5018 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005019 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08005020 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005021 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005022 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5023 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
5024 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5025 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5026 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5027
5028 // Move.
5029 x += 50;
5030 y += 75;
5031 processMove(mapper, x, y);
5032 processSync(mapper);
5033
5034 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5035 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5036 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5037 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5038 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5039 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5040 ASSERT_EQ(0, motionArgs.flags);
5041 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5042 ASSERT_EQ(0, motionArgs.buttonState);
5043 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005044 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08005045 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005046 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005047 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5048 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
5049 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5050 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5051 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5052
5053 // Up.
5054 processUp(mapper);
5055 processSync(mapper);
5056
5057 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5058 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5059 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5060 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5061 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5062 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5063 ASSERT_EQ(0, motionArgs.flags);
5064 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5065 ASSERT_EQ(0, motionArgs.buttonState);
5066 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005067 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08005068 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005069 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005070 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5071 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
5072 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5073 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5074 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5075
5076 // Should not have sent any more keys or motions.
5077 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5078 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5079}
5080
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005081TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_DoesNotRotateMotions) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005082 addConfigurationProperty("touch.deviceType", "touchScreen");
5083 prepareButtons();
5084 prepareAxes(POSITION);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005085 // InputReader works in the un-rotated coordinate space, so orientation-aware devices do not
5086 // need to be rotated. Touchscreens are orientation-aware by default.
Arpit Singha8c236b2023-04-25 13:56:05 +00005087 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005088
5089 NotifyMotionArgs args;
5090
5091 // Rotation 90.
Michael Wrighta9cf4192022-12-01 23:46:39 +00005092 prepareDisplay(ui::ROTATION_90);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005093 processDown(mapper, toRawX(50), toRawY(75));
5094 processSync(mapper);
5095
5096 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5097 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5098 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5099
5100 processUp(mapper);
5101 processSync(mapper);
5102 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5103}
5104
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005105TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_RotatesMotions) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005106 addConfigurationProperty("touch.deviceType", "touchScreen");
5107 prepareButtons();
5108 prepareAxes(POSITION);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005109 // Since InputReader works in the un-rotated coordinate space, only devices that are not
5110 // orientation-aware are affected by display rotation.
5111 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00005112 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005113
5114 NotifyMotionArgs args;
5115
5116 // Rotation 0.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005117 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005118 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005119 processDown(mapper, toRawX(50), toRawY(75));
5120 processSync(mapper);
5121
5122 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5123 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5124 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5125
5126 processUp(mapper);
5127 processSync(mapper);
5128 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5129
5130 // Rotation 90.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005131 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005132 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005133 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005134 processSync(mapper);
5135
5136 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5137 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5138 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5139
5140 processUp(mapper);
5141 processSync(mapper);
5142 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5143
5144 // Rotation 180.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005145 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005146 prepareDisplay(ui::ROTATION_180);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005147 processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
5148 processSync(mapper);
5149
5150 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5151 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5152 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5153
5154 processUp(mapper);
5155 processSync(mapper);
5156 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5157
5158 // Rotation 270.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005159 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005160 prepareDisplay(ui::ROTATION_270);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005161 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005162 processSync(mapper);
5163
5164 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5165 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5166 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5167
5168 processUp(mapper);
5169 processSync(mapper);
5170 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5171}
5172
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005173TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation0_RotatesMotions) {
5174 addConfigurationProperty("touch.deviceType", "touchScreen");
5175 prepareButtons();
5176 prepareAxes(POSITION);
5177 addConfigurationProperty("touch.orientationAware", "1");
5178 addConfigurationProperty("touch.orientation", "ORIENTATION_0");
5179 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005180 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005181 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005182 NotifyMotionArgs args;
5183
5184 // Orientation 0.
5185 processDown(mapper, toRawX(50), toRawY(75));
5186 processSync(mapper);
5187
5188 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5189 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5190 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5191
5192 processUp(mapper);
5193 processSync(mapper);
5194 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5195}
5196
5197TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation90_RotatesMotions) {
5198 addConfigurationProperty("touch.deviceType", "touchScreen");
5199 prepareButtons();
5200 prepareAxes(POSITION);
5201 addConfigurationProperty("touch.orientationAware", "1");
5202 addConfigurationProperty("touch.orientation", "ORIENTATION_90");
5203 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005204 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005205 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005206 NotifyMotionArgs args;
5207
5208 // Orientation 90.
5209 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
5210 processSync(mapper);
5211
5212 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5213 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5214 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5215
5216 processUp(mapper);
5217 processSync(mapper);
5218 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5219}
5220
5221TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation180_RotatesMotions) {
5222 addConfigurationProperty("touch.deviceType", "touchScreen");
5223 prepareButtons();
5224 prepareAxes(POSITION);
5225 addConfigurationProperty("touch.orientationAware", "1");
5226 addConfigurationProperty("touch.orientation", "ORIENTATION_180");
5227 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005228 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005229 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005230 NotifyMotionArgs args;
5231
5232 // Orientation 180.
5233 processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
5234 processSync(mapper);
5235
5236 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5237 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5238 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5239
5240 processUp(mapper);
5241 processSync(mapper);
5242 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5243}
5244
5245TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation270_RotatesMotions) {
5246 addConfigurationProperty("touch.deviceType", "touchScreen");
5247 prepareButtons();
5248 prepareAxes(POSITION);
5249 addConfigurationProperty("touch.orientationAware", "1");
5250 addConfigurationProperty("touch.orientation", "ORIENTATION_270");
5251 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005252 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005253 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005254 NotifyMotionArgs args;
5255
5256 // Orientation 270.
5257 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
5258 processSync(mapper);
5259
5260 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5261 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5262 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5263
5264 processUp(mapper);
5265 processSync(mapper);
5266 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5267}
5268
5269TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationSpecified_RotatesMotionWithDisplay) {
5270 addConfigurationProperty("touch.deviceType", "touchScreen");
5271 prepareButtons();
5272 prepareAxes(POSITION);
5273 // Since InputReader works in the un-rotated coordinate space, only devices that are not
5274 // orientation-aware are affected by display rotation.
5275 addConfigurationProperty("touch.orientationAware", "0");
5276 addConfigurationProperty("touch.orientation", "ORIENTATION_90");
Arpit Singha8c236b2023-04-25 13:56:05 +00005277 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005278
5279 NotifyMotionArgs args;
5280
5281 // Orientation 90, Rotation 0.
5282 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005283 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005284 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
5285 processSync(mapper);
5286
5287 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5288 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5289 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5290
5291 processUp(mapper);
5292 processSync(mapper);
5293 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5294
5295 // Orientation 90, Rotation 90.
5296 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005297 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005298 processDown(mapper, toRawX(50), toRawY(75));
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005299 processSync(mapper);
5300
5301 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5302 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5303 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5304
5305 processUp(mapper);
5306 processSync(mapper);
5307 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5308
5309 // Orientation 90, Rotation 180.
5310 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005311 prepareDisplay(ui::ROTATION_180);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005312 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
5313 processSync(mapper);
5314
5315 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5316 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5317 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5318
5319 processUp(mapper);
5320 processSync(mapper);
5321 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5322
5323 // Orientation 90, Rotation 270.
5324 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005325 prepareDisplay(ui::ROTATION_270);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005326 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 -07005327 processSync(mapper);
5328
5329 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5330 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5331 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5332
5333 processUp(mapper);
5334 processSync(mapper);
5335 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5336}
5337
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005338TEST_F(SingleTouchInputMapperTest, Process_IgnoresTouchesOutsidePhysicalFrame) {
5339 addConfigurationProperty("touch.deviceType", "touchScreen");
5340 prepareButtons();
5341 prepareAxes(POSITION);
5342 addConfigurationProperty("touch.orientationAware", "1");
5343 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005344 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005345
5346 // Set a physical frame in the display viewport.
5347 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
5348 viewport->physicalLeft = 20;
5349 viewport->physicalTop = 600;
5350 viewport->physicalRight = 30;
5351 viewport->physicalBottom = 610;
5352 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00005353 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005354
5355 // Start the touch.
5356 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
5357 processSync(mapper);
5358
5359 // Expect all input starting outside the physical frame to be ignored.
5360 const std::array<Point, 6> outsidePoints = {
5361 {{0, 0}, {19, 605}, {31, 605}, {25, 599}, {25, 611}, {DISPLAY_WIDTH, DISPLAY_HEIGHT}}};
5362 for (const auto& p : outsidePoints) {
5363 processMove(mapper, toRawX(p.x), toRawY(p.y));
5364 processSync(mapper);
5365 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5366 }
5367
5368 // Move the touch into the physical frame.
5369 processMove(mapper, toRawX(25), toRawY(605));
5370 processSync(mapper);
5371 NotifyMotionArgs args;
5372 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5373 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
5374 EXPECT_NEAR(25, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5375 EXPECT_NEAR(605, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5376
5377 // Once the touch down is reported, continue reporting input, even if it is outside the frame.
5378 for (const auto& p : outsidePoints) {
5379 processMove(mapper, toRawX(p.x), toRawY(p.y));
5380 processSync(mapper);
5381 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5382 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
5383 EXPECT_NEAR(p.x, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5384 EXPECT_NEAR(p.y, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5385 }
5386
5387 processUp(mapper);
5388 processSync(mapper);
5389 EXPECT_NO_FATAL_FAILURE(
5390 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
5391}
5392
Harry Cutts1db43992023-06-19 17:05:07 +00005393TEST_F(SingleTouchInputMapperTest, Process_DoesntCheckPhysicalFrameForTouchpads) {
5394 std::shared_ptr<FakePointerController> fakePointerController =
5395 std::make_shared<FakePointerController>();
5396 mFakePolicy->setPointerController(fakePointerController);
5397
5398 addConfigurationProperty("touch.deviceType", "pointer");
5399 prepareAxes(POSITION);
5400 prepareDisplay(ui::ROTATION_0);
5401 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
5402
5403 // Set a physical frame in the display viewport.
5404 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
5405 viewport->physicalLeft = 20;
5406 viewport->physicalTop = 600;
5407 viewport->physicalRight = 30;
5408 viewport->physicalBottom = 610;
5409 mFakePolicy->updateViewport(*viewport);
5410 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
5411
5412 // Start the touch.
5413 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
5414 processSync(mapper);
5415
5416 // Expect all input starting outside the physical frame to result in NotifyMotionArgs being
5417 // produced.
5418 const std::array<Point, 6> outsidePoints = {
5419 {{0, 0}, {19, 605}, {31, 605}, {25, 599}, {25, 611}, {DISPLAY_WIDTH, DISPLAY_HEIGHT}}};
5420 for (const auto& p : outsidePoints) {
5421 processMove(mapper, toRawX(p.x), toRawY(p.y));
5422 processSync(mapper);
5423 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5424 }
5425}
5426
Michael Wrightd02c5b62014-02-10 15:10:22 -08005427TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005428 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005429 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005430 prepareButtons();
5431 prepareAxes(POSITION | PRESSURE | TOOL | DISTANCE | TILT);
Arpit Singha8c236b2023-04-25 13:56:05 +00005432 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005433
5434 // These calculations are based on the input device calibration documentation.
5435 int32_t rawX = 100;
5436 int32_t rawY = 200;
5437 int32_t rawPressure = 10;
5438 int32_t rawToolMajor = 12;
5439 int32_t rawDistance = 2;
5440 int32_t rawTiltX = 30;
5441 int32_t rawTiltY = 110;
5442
5443 float x = toDisplayX(rawX);
5444 float y = toDisplayY(rawY);
5445 float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
5446 float size = float(rawToolMajor) / RAW_TOOL_MAX;
5447 float tool = float(rawToolMajor) * GEOMETRIC_SCALE;
5448 float distance = float(rawDistance);
5449
5450 float tiltCenter = (RAW_TILT_MAX + RAW_TILT_MIN) * 0.5f;
5451 float tiltScale = M_PI / 180;
5452 float tiltXAngle = (rawTiltX - tiltCenter) * tiltScale;
5453 float tiltYAngle = (rawTiltY - tiltCenter) * tiltScale;
5454 float orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
5455 float tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
5456
5457 processDown(mapper, rawX, rawY);
5458 processPressure(mapper, rawPressure);
5459 processToolMajor(mapper, rawToolMajor);
5460 processDistance(mapper, rawDistance);
5461 processTilt(mapper, rawTiltX, rawTiltY);
5462 processSync(mapper);
5463
5464 NotifyMotionArgs args;
5465 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5466 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
5467 x, y, pressure, size, tool, tool, tool, tool, orientation, distance));
5468 ASSERT_EQ(tilt, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TILT));
5469}
5470
Jason Gerecke489fda82012-09-07 17:19:40 -07005471TEST_F(SingleTouchInputMapperTest, Process_XYAxes_AffineCalibration) {
Jason Gerecke489fda82012-09-07 17:19:40 -07005472 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005473 prepareDisplay(ui::ROTATION_0);
Jason Gerecke489fda82012-09-07 17:19:40 -07005474 prepareLocationCalibration();
5475 prepareButtons();
5476 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005477 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Jason Gerecke489fda82012-09-07 17:19:40 -07005478
5479 int32_t rawX = 100;
5480 int32_t rawY = 200;
5481
5482 float x = toDisplayX(toCookedX(rawX, rawY));
5483 float y = toDisplayY(toCookedY(rawX, rawY));
5484
5485 processDown(mapper, rawX, rawY);
5486 processSync(mapper);
5487
5488 NotifyMotionArgs args;
5489 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5490 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
5491 x, y, 1, 0, 0, 0, 0, 0, 0, 0));
5492}
5493
Michael Wrightd02c5b62014-02-10 15:10:22 -08005494TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllButtons) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005495 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005496 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005497 prepareButtons();
5498 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005499 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005500
5501 NotifyMotionArgs motionArgs;
5502 NotifyKeyArgs keyArgs;
5503
5504 processDown(mapper, 100, 200);
5505 processSync(mapper);
5506 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5507 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5508 ASSERT_EQ(0, motionArgs.buttonState);
5509
5510 // press BTN_LEFT, release BTN_LEFT
5511 processKey(mapper, BTN_LEFT, 1);
5512 processSync(mapper);
5513 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5514 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5515 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
5516
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005517 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5518 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5519 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
5520
Michael Wrightd02c5b62014-02-10 15:10:22 -08005521 processKey(mapper, BTN_LEFT, 0);
5522 processSync(mapper);
5523 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005524 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005525 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005526
5527 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005528 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005529 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005530
5531 // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
5532 processKey(mapper, BTN_RIGHT, 1);
5533 processKey(mapper, BTN_MIDDLE, 1);
5534 processSync(mapper);
5535 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5536 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5537 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
5538 motionArgs.buttonState);
5539
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005540 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5541 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5542 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
5543
5544 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5545 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5546 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
5547 motionArgs.buttonState);
5548
Michael Wrightd02c5b62014-02-10 15:10:22 -08005549 processKey(mapper, BTN_RIGHT, 0);
5550 processSync(mapper);
5551 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005552 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005553 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005554
5555 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005556 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005557 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005558
5559 processKey(mapper, BTN_MIDDLE, 0);
5560 processSync(mapper);
5561 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005562 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005563 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005564
5565 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005566 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005567 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005568
5569 // press BTN_BACK, release BTN_BACK
5570 processKey(mapper, BTN_BACK, 1);
5571 processSync(mapper);
5572 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5573 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5574 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005575
Michael Wrightd02c5b62014-02-10 15:10:22 -08005576 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005577 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005578 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
5579
5580 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5581 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5582 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005583
5584 processKey(mapper, BTN_BACK, 0);
5585 processSync(mapper);
5586 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005587 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005588 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005589
5590 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(0, motionArgs.buttonState);
5593
Michael Wrightd02c5b62014-02-10 15:10:22 -08005594 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5595 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5596 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
5597
5598 // press BTN_SIDE, release BTN_SIDE
5599 processKey(mapper, BTN_SIDE, 1);
5600 processSync(mapper);
5601 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5602 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5603 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005604
Michael Wrightd02c5b62014-02-10 15:10:22 -08005605 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005606 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005607 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
5608
5609 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5610 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5611 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005612
5613 processKey(mapper, BTN_SIDE, 0);
5614 processSync(mapper);
5615 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005616 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005617 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005618
5619 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(0, motionArgs.buttonState);
5622
Michael Wrightd02c5b62014-02-10 15:10:22 -08005623 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5624 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5625 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
5626
5627 // press BTN_FORWARD, release BTN_FORWARD
5628 processKey(mapper, BTN_FORWARD, 1);
5629 processSync(mapper);
5630 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5631 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5632 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005633
Michael Wrightd02c5b62014-02-10 15:10:22 -08005634 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005635 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005636 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
5637
5638 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5639 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5640 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005641
5642 processKey(mapper, BTN_FORWARD, 0);
5643 processSync(mapper);
5644 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005645 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005646 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005647
5648 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(0, motionArgs.buttonState);
5651
Michael Wrightd02c5b62014-02-10 15:10:22 -08005652 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5653 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5654 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
5655
5656 // press BTN_EXTRA, release BTN_EXTRA
5657 processKey(mapper, BTN_EXTRA, 1);
5658 processSync(mapper);
5659 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5660 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5661 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005662
Michael Wrightd02c5b62014-02-10 15:10:22 -08005663 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005664 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005665 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
5666
5667 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5668 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5669 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005670
5671 processKey(mapper, BTN_EXTRA, 0);
5672 processSync(mapper);
5673 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005674 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005675 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005676
5677 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(0, motionArgs.buttonState);
5680
Michael Wrightd02c5b62014-02-10 15:10:22 -08005681 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5682 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5683 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
5684
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005685 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5686
Michael Wrightd02c5b62014-02-10 15:10:22 -08005687 // press BTN_STYLUS, release BTN_STYLUS
5688 processKey(mapper, BTN_STYLUS, 1);
5689 processSync(mapper);
5690 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5691 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005692 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
5693
5694 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5695 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5696 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005697
5698 processKey(mapper, BTN_STYLUS, 0);
5699 processSync(mapper);
5700 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005701 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005702 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005703
5704 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005705 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005706 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005707
5708 // press BTN_STYLUS2, release BTN_STYLUS2
5709 processKey(mapper, BTN_STYLUS2, 1);
5710 processSync(mapper);
5711 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5712 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005713 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
5714
5715 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5716 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5717 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005718
5719 processKey(mapper, BTN_STYLUS2, 0);
5720 processSync(mapper);
5721 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005722 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005723 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005724
5725 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005726 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005727 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005728
5729 // release touch
5730 processUp(mapper);
5731 processSync(mapper);
5732 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5733 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5734 ASSERT_EQ(0, motionArgs.buttonState);
5735}
5736
5737TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005738 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005739 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005740 prepareButtons();
5741 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005742 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005743
5744 NotifyMotionArgs motionArgs;
5745
5746 // default tool type is finger
5747 processDown(mapper, 100, 200);
5748 processSync(mapper);
5749 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5750 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005751 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005752
5753 // eraser
5754 processKey(mapper, BTN_TOOL_RUBBER, 1);
5755 processSync(mapper);
5756 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5757 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005758 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005759
5760 // stylus
5761 processKey(mapper, BTN_TOOL_RUBBER, 0);
5762 processKey(mapper, BTN_TOOL_PEN, 1);
5763 processSync(mapper);
5764 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5765 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005766 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005767
5768 // brush
5769 processKey(mapper, BTN_TOOL_PEN, 0);
5770 processKey(mapper, BTN_TOOL_BRUSH, 1);
5771 processSync(mapper);
5772 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5773 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005774 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005775
5776 // pencil
5777 processKey(mapper, BTN_TOOL_BRUSH, 0);
5778 processKey(mapper, BTN_TOOL_PENCIL, 1);
5779 processSync(mapper);
5780 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5781 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005782 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005783
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08005784 // air-brush
Michael Wrightd02c5b62014-02-10 15:10:22 -08005785 processKey(mapper, BTN_TOOL_PENCIL, 0);
5786 processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
5787 processSync(mapper);
5788 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5789 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005790 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005791
5792 // mouse
5793 processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
5794 processKey(mapper, BTN_TOOL_MOUSE, 1);
5795 processSync(mapper);
5796 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5797 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005798 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005799
5800 // lens
5801 processKey(mapper, BTN_TOOL_MOUSE, 0);
5802 processKey(mapper, BTN_TOOL_LENS, 1);
5803 processSync(mapper);
5804 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5805 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005806 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005807
5808 // double-tap
5809 processKey(mapper, BTN_TOOL_LENS, 0);
5810 processKey(mapper, BTN_TOOL_DOUBLETAP, 1);
5811 processSync(mapper);
5812 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5813 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005814 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005815
5816 // triple-tap
5817 processKey(mapper, BTN_TOOL_DOUBLETAP, 0);
5818 processKey(mapper, BTN_TOOL_TRIPLETAP, 1);
5819 processSync(mapper);
5820 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5821 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005822 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005823
5824 // quad-tap
5825 processKey(mapper, BTN_TOOL_TRIPLETAP, 0);
5826 processKey(mapper, BTN_TOOL_QUADTAP, 1);
5827 processSync(mapper);
5828 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5829 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005830 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005831
5832 // finger
5833 processKey(mapper, BTN_TOOL_QUADTAP, 0);
5834 processKey(mapper, BTN_TOOL_FINGER, 1);
5835 processSync(mapper);
5836 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5837 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005838 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005839
5840 // stylus trumps finger
5841 processKey(mapper, BTN_TOOL_PEN, 1);
5842 processSync(mapper);
5843 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5844 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005845 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005846
5847 // eraser trumps stylus
5848 processKey(mapper, BTN_TOOL_RUBBER, 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::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005853
5854 // mouse trumps eraser
5855 processKey(mapper, BTN_TOOL_MOUSE, 1);
5856 processSync(mapper);
5857 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5858 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005859 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005860
5861 // back to default tool type
5862 processKey(mapper, BTN_TOOL_MOUSE, 0);
5863 processKey(mapper, BTN_TOOL_RUBBER, 0);
5864 processKey(mapper, BTN_TOOL_PEN, 0);
5865 processKey(mapper, BTN_TOOL_FINGER, 0);
5866 processSync(mapper);
5867 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5868 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005869 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005870}
5871
5872TEST_F(SingleTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005873 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005874 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005875 prepareButtons();
5876 prepareAxes(POSITION);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08005877 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_FINGER, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005878 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005879
5880 NotifyMotionArgs motionArgs;
5881
5882 // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0
5883 processKey(mapper, BTN_TOOL_FINGER, 1);
5884 processMove(mapper, 100, 200);
5885 processSync(mapper);
5886 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5887 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5888 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5889 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5890
5891 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5892 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5893 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5894 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5895
5896 // move a little
5897 processMove(mapper, 150, 250);
5898 processSync(mapper);
5899 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5900 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5901 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5902 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5903
5904 // down when BTN_TOUCH is pressed, pressure defaults to 1
5905 processKey(mapper, BTN_TOUCH, 1);
5906 processSync(mapper);
5907 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5908 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5909 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5910 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5911
5912 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5913 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5914 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5915 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5916
5917 // up when BTN_TOUCH is released, hover restored
5918 processKey(mapper, BTN_TOUCH, 0);
5919 processSync(mapper);
5920 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5921 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5922 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5923 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5924
5925 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5926 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5927 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5928 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5929
5930 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5931 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5932 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5933 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5934
5935 // exit hover when pointer goes away
5936 processKey(mapper, BTN_TOOL_FINGER, 0);
5937 processSync(mapper);
5938 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5939 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5940 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5941 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5942}
5943
5944TEST_F(SingleTouchInputMapperTest, Process_WhenAbsPressureIsPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005945 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005946 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005947 prepareButtons();
5948 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00005949 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005950
5951 NotifyMotionArgs motionArgs;
5952
5953 // initially hovering because pressure is 0
5954 processDown(mapper, 100, 200);
5955 processPressure(mapper, 0);
5956 processSync(mapper);
5957 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5958 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5959 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5960 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5961
5962 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5963 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5964 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5965 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5966
5967 // move a little
5968 processMove(mapper, 150, 250);
5969 processSync(mapper);
5970 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5971 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5972 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5973 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5974
5975 // down when pressure is non-zero
5976 processPressure(mapper, RAW_PRESSURE_MAX);
5977 processSync(mapper);
5978 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5979 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5980 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5981 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5982
5983 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5984 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5985 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5986 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5987
5988 // up when pressure becomes 0, hover restored
5989 processPressure(mapper, 0);
5990 processSync(mapper);
5991 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5992 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5993 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5994 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5995
5996 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5997 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5998 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5999 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6000
6001 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6002 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
6003 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6004 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6005
6006 // exit hover when pointer goes away
6007 processUp(mapper);
6008 processSync(mapper);
6009 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6010 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
6011 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
6012 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
6013}
6014
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006015TEST_F(SingleTouchInputMapperTest, Reset_CancelsOngoingGesture) {
6016 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006017 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006018 prepareButtons();
6019 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00006020 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006021
6022 // Touch down.
6023 processDown(mapper, 100, 200);
6024 processPressure(mapper, 1);
6025 processSync(mapper);
6026 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6027 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
6028
6029 // Reset the mapper. This should cancel the ongoing gesture.
6030 resetMapper(mapper, ARBITRARY_TIME);
6031 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6032 WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
6033
6034 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6035}
6036
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006037TEST_F(SingleTouchInputMapperTest, Reset_RecreatesTouchState) {
6038 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006039 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006040 prepareButtons();
6041 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00006042 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006043
6044 // Set the initial state for the touch pointer.
6045 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_X, 100);
6046 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_Y, 200);
6047 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_PRESSURE, RAW_PRESSURE_MAX);
6048 mFakeEventHub->setScanCodeState(EVENTHUB_ID, BTN_TOUCH, 1);
6049
6050 // Reset the mapper. When the mapper is reset, we expect it to attempt to recreate the touch
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006051 // state by reading the current axis values. Since there was no ongoing gesture, calling reset
6052 // does not generate any events.
6053 resetMapper(mapper, ARBITRARY_TIME);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006054
6055 // Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
6056 // the recreated touch state to generate a down event.
6057 processSync(mapper);
6058 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6059 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPressure(1.f))));
6060
6061 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6062}
6063
lilinnan687e58f2022-07-19 16:00:50 +08006064TEST_F(SingleTouchInputMapperTest,
6065 Process_WhenViewportDisplayIdChanged_TouchIsCanceledAndDeviceIsReset) {
6066 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006067 prepareDisplay(ui::ROTATION_0);
lilinnan687e58f2022-07-19 16:00:50 +08006068 prepareButtons();
6069 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006070 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
lilinnan687e58f2022-07-19 16:00:50 +08006071 NotifyMotionArgs motionArgs;
6072
6073 // Down.
Prabir Pradhan3e5ec702022-07-29 16:26:24 +00006074 processDown(mapper, 100, 200);
lilinnan687e58f2022-07-19 16:00:50 +08006075 processSync(mapper);
6076
6077 // We should receive a down event
6078 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6079 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6080
6081 // Change display id
6082 clearViewports();
6083 prepareSecondaryDisplay(ViewportType::INTERNAL);
6084
6085 // We should receive a cancel event
6086 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6087 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
6088 // Then receive reset called
6089 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6090}
6091
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006092TEST_F(SingleTouchInputMapperTest,
6093 Process_WhenViewportActiveStatusChanged_TouchIsCanceledAndDeviceIsReset) {
6094 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006095 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006096 prepareButtons();
6097 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006098 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006099 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6100 NotifyMotionArgs motionArgs;
6101
6102 // Start a new gesture.
6103 processDown(mapper, 100, 200);
6104 processSync(mapper);
6105 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6106 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6107
6108 // Make the viewport inactive. This will put the device in disabled mode.
6109 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6110 viewport->isActive = false;
6111 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006112 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006113
6114 // We should receive a cancel event for the ongoing gesture.
6115 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6116 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
6117 // Then we should be notified that the device was reset.
6118 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6119
6120 // No events are generated while the viewport is inactive.
6121 processMove(mapper, 101, 201);
6122 processSync(mapper);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006123 processUp(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006124 processSync(mapper);
6125 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6126
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006127 // Start a new gesture while the viewport is still inactive.
6128 processDown(mapper, 300, 400);
6129 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_X, 300);
6130 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_Y, 400);
6131 mFakeEventHub->setScanCodeState(EVENTHUB_ID, BTN_TOUCH, 1);
6132 processSync(mapper);
6133
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006134 // Make the viewport active again. The device should resume processing events.
6135 viewport->isActive = true;
6136 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006137 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006138
6139 // The device is reset because it changes back to direct mode, without generating any events.
6140 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6141 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6142
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006143 // In the next sync, the touch state that was recreated when the device was reset is reported.
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006144 processSync(mapper);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006145 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6146 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006147
6148 // No more events.
6149 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6150 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
6151}
6152
Prabir Pradhan211ba622022-10-31 21:09:21 +00006153TEST_F(SingleTouchInputMapperTest, ButtonIsReleasedOnTouchUp) {
6154 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006155 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan211ba622022-10-31 21:09:21 +00006156 prepareButtons();
6157 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006158 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan211ba622022-10-31 21:09:21 +00006159 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6160
6161 // Press a stylus button.
6162 processKey(mapper, BTN_STYLUS, 1);
6163 processSync(mapper);
6164
6165 // Start a touch gesture and ensure the BUTTON_PRESS event is generated.
6166 processDown(mapper, 100, 200);
6167 processSync(mapper);
6168 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6169 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6170 WithCoords(toDisplayX(100), toDisplayY(200)),
6171 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6172 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6173 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
6174 WithCoords(toDisplayX(100), toDisplayY(200)),
6175 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6176
6177 // Release the touch gesture. Ensure that the BUTTON_RELEASE event is generated even though
6178 // the button has not actually been released, since there will be no pointers through which the
6179 // button state can be reported. The event is generated at the location of the pointer before
6180 // it went up.
6181 processUp(mapper);
6182 processSync(mapper);
6183 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6184 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
6185 WithCoords(toDisplayX(100), toDisplayY(200)), WithButtonState(0))));
6186 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6187 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6188 WithCoords(toDisplayX(100), toDisplayY(200)), WithButtonState(0))));
6189}
6190
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00006191TEST_F(SingleTouchInputMapperTest, StylusButtonMotionEventsDisabled) {
6192 addConfigurationProperty("touch.deviceType", "touchScreen");
6193 prepareDisplay(ui::ROTATION_0);
6194 prepareButtons();
6195 prepareAxes(POSITION);
6196
6197 mFakePolicy->setStylusButtonMotionEventsEnabled(false);
6198
Arpit Singha8c236b2023-04-25 13:56:05 +00006199 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00006200 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6201
6202 // Press a stylus button.
6203 processKey(mapper, BTN_STYLUS, 1);
6204 processSync(mapper);
6205
6206 // Start a touch gesture and ensure that the stylus button is not reported.
6207 processDown(mapper, 100, 200);
6208 processSync(mapper);
6209 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6210 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithButtonState(0))));
6211
6212 // Release and press the stylus button again.
6213 processKey(mapper, BTN_STYLUS, 0);
6214 processSync(mapper);
6215 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6216 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
6217 processKey(mapper, BTN_STYLUS, 1);
6218 processSync(mapper);
6219 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6220 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
6221
6222 // Release the touch gesture.
6223 processUp(mapper);
6224 processSync(mapper);
6225 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6226 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
6227
6228 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6229}
6230
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006231TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsSetToTouchNavigation_setsCorrectType) {
6232 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
6233 prepareDisplay(ui::ROTATION_0);
6234 prepareButtons();
6235 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006236 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006237 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6238
6239 ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION, mapper.getSources());
6240}
6241
Seunghwan Choi356026c2023-02-01 14:37:25 +09006242TEST_F(SingleTouchInputMapperTest, Process_WhenConfigEnabled_ShouldShowDirectStylusPointer) {
6243 std::shared_ptr<FakePointerController> fakePointerController =
6244 std::make_shared<FakePointerController>();
6245 addConfigurationProperty("touch.deviceType", "touchScreen");
6246 prepareDisplay(ui::ROTATION_0);
6247 prepareButtons();
6248 prepareAxes(POSITION);
6249 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
6250 mFakePolicy->setPointerController(fakePointerController);
6251 mFakePolicy->setStylusPointerIconEnabled(true);
Arpit Singha8c236b2023-04-25 13:56:05 +00006252 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Seunghwan Choi356026c2023-02-01 14:37:25 +09006253
6254 processKey(mapper, BTN_TOOL_PEN, 1);
6255 processMove(mapper, 100, 200);
6256 processSync(mapper);
6257 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6258 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006259 WithToolType(ToolType::STYLUS),
Seunghwan Choi356026c2023-02-01 14:37:25 +09006260 WithPointerCoords(0, toDisplayX(100), toDisplayY(200)))));
6261 ASSERT_TRUE(fakePointerController->isPointerShown());
6262 ASSERT_NO_FATAL_FAILURE(
6263 fakePointerController->assertPosition(toDisplayX(100), toDisplayY(200)));
6264}
6265
6266TEST_F(SingleTouchInputMapperTest, Process_WhenConfigDisabled_ShouldNotShowDirectStylusPointer) {
6267 std::shared_ptr<FakePointerController> fakePointerController =
6268 std::make_shared<FakePointerController>();
6269 addConfigurationProperty("touch.deviceType", "touchScreen");
6270 prepareDisplay(ui::ROTATION_0);
6271 prepareButtons();
6272 prepareAxes(POSITION);
6273 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
6274 mFakePolicy->setPointerController(fakePointerController);
6275 mFakePolicy->setStylusPointerIconEnabled(false);
Arpit Singha8c236b2023-04-25 13:56:05 +00006276 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Seunghwan Choi356026c2023-02-01 14:37:25 +09006277
6278 processKey(mapper, BTN_TOOL_PEN, 1);
6279 processMove(mapper, 100, 200);
6280 processSync(mapper);
6281 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6282 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006283 WithToolType(ToolType::STYLUS),
Seunghwan Choi356026c2023-02-01 14:37:25 +09006284 WithPointerCoords(0, toDisplayX(100), toDisplayY(200)))));
6285 ASSERT_FALSE(fakePointerController->isPointerShown());
6286}
6287
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006288TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsChangedToTouchNavigation_updatesDeviceType) {
6289 // Initialize the device without setting device source to touch navigation.
6290 addConfigurationProperty("touch.deviceType", "touchScreen");
6291 prepareDisplay(ui::ROTATION_0);
6292 prepareButtons();
6293 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006294 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006295
6296 // Ensure that the device is created as a touchscreen, not touch navigation.
6297 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
6298
6299 // Add device type association after the device was created.
6300 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
6301
6302 // Send update to the mapper.
6303 std::list<NotifyArgs> unused2 =
6304 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006305 InputReaderConfiguration::Change::DEVICE_TYPE /*changes*/);
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006306
6307 // Check whether device type update was successful.
6308 ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION, mDevice->getSources());
6309}
6310
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006311TEST_F(SingleTouchInputMapperTest, HoverEventsOutsidePhysicalFrameAreIgnored) {
6312 // Initialize the device without setting device source to touch navigation.
6313 addConfigurationProperty("touch.deviceType", "touchScreen");
6314 prepareDisplay(ui::ROTATION_0);
6315 prepareButtons();
6316 prepareAxes(POSITION);
6317 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
6318
6319 // Set a physical frame in the display viewport.
6320 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6321 viewport->physicalLeft = 0;
6322 viewport->physicalTop = 0;
6323 viewport->physicalRight = DISPLAY_WIDTH / 2;
6324 viewport->physicalBottom = DISPLAY_HEIGHT / 2;
6325 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006326 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006327
Arpit Singha8c236b2023-04-25 13:56:05 +00006328 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006329
6330 // Hovering inside the physical frame produces events.
6331 processKey(mapper, BTN_TOOL_PEN, 1);
6332 processMove(mapper, RAW_X_MIN + 1, RAW_Y_MIN + 1);
6333 processSync(mapper);
6334 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6335 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)));
6336 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6337 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)));
6338
6339 // Leaving the physical frame ends the hovering gesture.
6340 processMove(mapper, RAW_X_MAX - 1, RAW_Y_MAX - 1);
6341 processSync(mapper);
6342 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6343 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT)));
6344
6345 // Moving outside the physical frame does not produce events.
6346 processMove(mapper, RAW_X_MAX - 2, RAW_Y_MAX - 2);
6347 processSync(mapper);
6348 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6349
6350 // Re-entering the physical frame produces events.
6351 processMove(mapper, RAW_X_MIN, RAW_Y_MIN);
6352 processSync(mapper);
6353 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6354 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)));
6355 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6356 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)));
6357}
6358
Prabir Pradhan5632d622021-09-06 07:57:20 -07006359// --- TouchDisplayProjectionTest ---
6360
6361class TouchDisplayProjectionTest : public SingleTouchInputMapperTest {
6362public:
6363 // The values inside DisplayViewport are expected to be pre-rotated. This updates the current
6364 // DisplayViewport to pre-rotate the values. The viewport's physical display will be set to the
6365 // rotated equivalent of the given un-rotated physical display bounds.
Prabir Pradhana9df3162022-12-05 23:57:27 +00006366 void configurePhysicalDisplay(ui::Rotation orientation, Rect naturalPhysicalDisplay,
6367 int32_t naturalDisplayWidth = DISPLAY_WIDTH,
6368 int32_t naturalDisplayHeight = DISPLAY_HEIGHT) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006369 uint32_t inverseRotationFlags;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006370 auto rotatedWidth = naturalDisplayWidth;
6371 auto rotatedHeight = naturalDisplayHeight;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006372 switch (orientation) {
Michael Wrighta9cf4192022-12-01 23:46:39 +00006373 case ui::ROTATION_90:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006374 inverseRotationFlags = ui::Transform::ROT_270;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006375 std::swap(rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006376 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006377 case ui::ROTATION_180:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006378 inverseRotationFlags = ui::Transform::ROT_180;
6379 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006380 case ui::ROTATION_270:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006381 inverseRotationFlags = ui::Transform::ROT_90;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006382 std::swap(rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006383 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006384 case ui::ROTATION_0:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006385 inverseRotationFlags = ui::Transform::ROT_0;
6386 break;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006387 }
6388
Prabir Pradhana9df3162022-12-05 23:57:27 +00006389 const ui::Transform rotation(inverseRotationFlags, rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006390 const Rect rotatedPhysicalDisplay = rotation.transform(naturalPhysicalDisplay);
6391
6392 std::optional<DisplayViewport> internalViewport =
6393 *mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6394 DisplayViewport& v = *internalViewport;
6395 v.displayId = DISPLAY_ID;
6396 v.orientation = orientation;
6397
6398 v.logicalLeft = 0;
6399 v.logicalTop = 0;
6400 v.logicalRight = 100;
6401 v.logicalBottom = 100;
6402
6403 v.physicalLeft = rotatedPhysicalDisplay.left;
6404 v.physicalTop = rotatedPhysicalDisplay.top;
6405 v.physicalRight = rotatedPhysicalDisplay.right;
6406 v.physicalBottom = rotatedPhysicalDisplay.bottom;
6407
Prabir Pradhana9df3162022-12-05 23:57:27 +00006408 v.deviceWidth = rotatedWidth;
6409 v.deviceHeight = rotatedHeight;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006410
6411 v.isActive = true;
6412 v.uniqueId = UNIQUE_ID;
6413 v.type = ViewportType::INTERNAL;
6414 mFakePolicy->updateViewport(v);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006415 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006416 }
6417
6418 void assertReceivedMove(const Point& point) {
6419 NotifyMotionArgs motionArgs;
6420 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6421 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006422 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Prabir Pradhan5632d622021-09-06 07:57:20 -07006423 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], point.x, point.y,
6424 1, 0, 0, 0, 0, 0, 0, 0));
6425 }
6426};
6427
6428TEST_F(TouchDisplayProjectionTest, IgnoresTouchesOutsidePhysicalDisplay) {
6429 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006430 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006431
6432 prepareButtons();
6433 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006434 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan5632d622021-09-06 07:57:20 -07006435
6436 NotifyMotionArgs motionArgs;
6437
6438 // Configure the DisplayViewport such that the logical display maps to a subsection of
6439 // the display panel called the physical display. Here, the physical display is bounded by the
6440 // points (10, 20) and (70, 160) inside the display space, which is of the size 400 x 800.
6441 static const Rect kPhysicalDisplay{10, 20, 70, 160};
6442 static const std::array<Point, 6> kPointsOutsidePhysicalDisplay{
6443 {{-10, -10}, {0, 0}, {5, 100}, {50, 15}, {75, 100}, {50, 165}}};
6444
Michael Wrighta9cf4192022-12-01 23:46:39 +00006445 for (auto orientation : {ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180, ui::ROTATION_270}) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006446 configurePhysicalDisplay(orientation, kPhysicalDisplay);
6447
6448 // Touches outside the physical display should be ignored, and should not generate any
6449 // events. Ensure touches at the following points that lie outside of the physical display
6450 // area do not generate any events.
6451 for (const auto& point : kPointsOutsidePhysicalDisplay) {
6452 processDown(mapper, toRawX(point.x), toRawY(point.y));
6453 processSync(mapper);
6454 processUp(mapper);
6455 processSync(mapper);
6456 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled())
6457 << "Unexpected event generated for touch outside physical display at point: "
6458 << point.x << ", " << point.y;
6459 }
6460 }
6461}
6462
6463TEST_F(TouchDisplayProjectionTest, EmitsTouchDownAfterEnteringPhysicalDisplay) {
6464 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006465 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006466
6467 prepareButtons();
6468 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006469 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan5632d622021-09-06 07:57:20 -07006470
6471 NotifyMotionArgs motionArgs;
6472
6473 // Configure the DisplayViewport such that the logical display maps to a subsection of
6474 // the display panel called the physical display. Here, the physical display is bounded by the
6475 // points (10, 20) and (70, 160) inside the display space, which is of the size 400 x 800.
6476 static const Rect kPhysicalDisplay{10, 20, 70, 160};
6477
Michael Wrighta9cf4192022-12-01 23:46:39 +00006478 for (auto orientation : {ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180, ui::ROTATION_270}) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006479 configurePhysicalDisplay(orientation, kPhysicalDisplay);
6480
6481 // Touches that start outside the physical display should be ignored until it enters the
6482 // physical display bounds, at which point it should generate a down event. Start a touch at
6483 // the point (5, 100), which is outside the physical display bounds.
6484 static const Point kOutsidePoint{5, 100};
6485 processDown(mapper, toRawX(kOutsidePoint.x), toRawY(kOutsidePoint.y));
6486 processSync(mapper);
6487 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6488
6489 // Move the touch into the physical display area. This should generate a pointer down.
6490 processMove(mapper, toRawX(11), toRawY(21));
6491 processSync(mapper);
6492 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6493 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006494 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Prabir Pradhan5632d622021-09-06 07:57:20 -07006495 ASSERT_NO_FATAL_FAILURE(
6496 assertPointerCoords(motionArgs.pointerCoords[0], 11, 21, 1, 0, 0, 0, 0, 0, 0, 0));
6497
6498 // Move the touch inside the physical display area. This should generate a pointer move.
6499 processMove(mapper, toRawX(69), toRawY(159));
6500 processSync(mapper);
6501 assertReceivedMove({69, 159});
6502
6503 // Move outside the physical display area. Since the pointer is already down, this should
6504 // now continue generating events.
6505 processMove(mapper, toRawX(kOutsidePoint.x), toRawY(kOutsidePoint.y));
6506 processSync(mapper);
6507 assertReceivedMove(kOutsidePoint);
6508
6509 // Release. This should generate a pointer up.
6510 processUp(mapper);
6511 processSync(mapper);
6512 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6513 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
6514 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], kOutsidePoint.x,
6515 kOutsidePoint.y, 1, 0, 0, 0, 0, 0, 0, 0));
6516
6517 // Ensure no more events were generated.
6518 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
6519 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6520 }
6521}
6522
Prabir Pradhana9df3162022-12-05 23:57:27 +00006523// --- TouchscreenPrecisionTests ---
6524
6525// This test suite is used to ensure that touchscreen devices are scaled and configured correctly
6526// in various orientations and with different display rotations. We configure the touchscreen to
6527// have a higher resolution than that of the display by an integer scale factor in each axis so that
6528// we can enforce that coordinates match precisely as expected.
6529class TouchscreenPrecisionTestsFixture : public TouchDisplayProjectionTest,
6530 public ::testing::WithParamInterface<ui::Rotation> {
6531public:
6532 void SetUp() override {
6533 SingleTouchInputMapperTest::SetUp();
6534
6535 // Prepare the raw axes to have twice the resolution of the display in the X axis and
6536 // four times the resolution of the display in the Y axis.
6537 prepareButtons();
6538 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, PRECISION_RAW_X_MIN, PRECISION_RAW_X_MAX,
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006539 PRECISION_RAW_X_FLAT, PRECISION_RAW_X_FUZZ,
6540 PRECISION_RAW_X_RES);
Prabir Pradhana9df3162022-12-05 23:57:27 +00006541 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, PRECISION_RAW_Y_MIN, PRECISION_RAW_Y_MAX,
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006542 PRECISION_RAW_Y_FLAT, PRECISION_RAW_Y_FUZZ,
6543 PRECISION_RAW_Y_RES);
Prabir Pradhana9df3162022-12-05 23:57:27 +00006544 }
6545
6546 static const int32_t PRECISION_RAW_X_MIN = TouchInputMapperTest::RAW_X_MIN;
6547 static const int32_t PRECISION_RAW_X_MAX = PRECISION_RAW_X_MIN + DISPLAY_WIDTH * 2 - 1;
6548 static const int32_t PRECISION_RAW_Y_MIN = TouchInputMapperTest::RAW_Y_MIN;
6549 static const int32_t PRECISION_RAW_Y_MAX = PRECISION_RAW_Y_MIN + DISPLAY_HEIGHT * 4 - 1;
6550
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006551 static const int32_t PRECISION_RAW_X_RES = 50; // units per millimeter
6552 static const int32_t PRECISION_RAW_Y_RES = 100; // units per millimeter
6553
6554 static const int32_t PRECISION_RAW_X_FLAT = 16;
6555 static const int32_t PRECISION_RAW_Y_FLAT = 32;
6556
6557 static const int32_t PRECISION_RAW_X_FUZZ = 4;
6558 static const int32_t PRECISION_RAW_Y_FUZZ = 8;
6559
Prabir Pradhana9df3162022-12-05 23:57:27 +00006560 static const std::array<Point, 4> kRawCorners;
6561};
6562
6563const std::array<Point, 4> TouchscreenPrecisionTestsFixture::kRawCorners = {{
6564 {PRECISION_RAW_X_MIN, PRECISION_RAW_Y_MIN}, // left-top
6565 {PRECISION_RAW_X_MAX, PRECISION_RAW_Y_MIN}, // right-top
6566 {PRECISION_RAW_X_MAX, PRECISION_RAW_Y_MAX}, // right-bottom
6567 {PRECISION_RAW_X_MIN, PRECISION_RAW_Y_MAX}, // left-bottom
6568}};
6569
6570// Tests for how the touchscreen is oriented relative to the natural orientation of the display.
6571// For example, if a touchscreen is configured with an orientation of 90 degrees, it is a portrait
6572// touchscreen panel that is used on a device whose natural display orientation is in landscape.
6573TEST_P(TouchscreenPrecisionTestsFixture, OrientationPrecision) {
6574 enum class Orientation {
6575 ORIENTATION_0 = ui::toRotationInt(ui::ROTATION_0),
6576 ORIENTATION_90 = ui::toRotationInt(ui::ROTATION_90),
6577 ORIENTATION_180 = ui::toRotationInt(ui::ROTATION_180),
6578 ORIENTATION_270 = ui::toRotationInt(ui::ROTATION_270),
6579 ftl_last = ORIENTATION_270,
6580 };
6581 using Orientation::ORIENTATION_0, Orientation::ORIENTATION_90, Orientation::ORIENTATION_180,
6582 Orientation::ORIENTATION_270;
6583 static const std::map<Orientation, std::array<vec2, 4> /*mappedCorners*/> kMappedCorners = {
6584 {ORIENTATION_0, {{{0, 0}, {479.5, 0}, {479.5, 799.75}, {0, 799.75}}}},
6585 {ORIENTATION_90, {{{0, 479.5}, {0, 0}, {799.75, 0}, {799.75, 479.5}}}},
6586 {ORIENTATION_180, {{{479.5, 799.75}, {0, 799.75}, {0, 0}, {479.5, 0}}}},
6587 {ORIENTATION_270, {{{799.75, 0}, {799.75, 479.5}, {0, 479.5}, {0, 0}}}},
6588 };
6589
6590 const auto touchscreenOrientation = static_cast<Orientation>(ui::toRotationInt(GetParam()));
6591
6592 // Configure the touchscreen as being installed in the one of the four different orientations
6593 // relative to the display.
6594 addConfigurationProperty("touch.deviceType", "touchScreen");
6595 addConfigurationProperty("touch.orientation", ftl::enum_string(touchscreenOrientation).c_str());
6596 prepareDisplay(ui::ROTATION_0);
6597
Arpit Singha8c236b2023-04-25 13:56:05 +00006598 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhana9df3162022-12-05 23:57:27 +00006599
6600 // If the touchscreen is installed in a rotated orientation relative to the display (i.e. in
6601 // orientations of either 90 or 270) this means the display's natural resolution will be
6602 // flipped.
6603 const bool displayRotated =
6604 touchscreenOrientation == ORIENTATION_90 || touchscreenOrientation == ORIENTATION_270;
6605 const int32_t width = displayRotated ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
6606 const int32_t height = displayRotated ? DISPLAY_WIDTH : DISPLAY_HEIGHT;
6607 const Rect physicalFrame{0, 0, width, height};
6608 configurePhysicalDisplay(ui::ROTATION_0, physicalFrame, width, height);
6609
6610 const auto& expectedPoints = kMappedCorners.at(touchscreenOrientation);
6611 const float expectedPrecisionX = displayRotated ? 4 : 2;
6612 const float expectedPrecisionY = displayRotated ? 2 : 4;
6613
6614 // Test all four corners.
6615 for (int i = 0; i < 4; i++) {
6616 const auto& raw = kRawCorners[i];
6617 processDown(mapper, raw.x, raw.y);
6618 processSync(mapper);
6619 const auto& expected = expectedPoints[i];
6620 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6621 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6622 WithCoords(expected.x, expected.y),
6623 WithPrecision(expectedPrecisionX, expectedPrecisionY))))
6624 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6625 << "with touchscreen orientation "
6626 << ftl::enum_string(touchscreenOrientation).c_str() << ", expected point ("
6627 << expected.x << ", " << expected.y << ").";
6628 processUp(mapper);
6629 processSync(mapper);
6630 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6631 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6632 WithCoords(expected.x, expected.y))));
6633 }
6634}
6635
Prabir Pradhan82687402022-12-06 01:32:53 +00006636TEST_P(TouchscreenPrecisionTestsFixture, RotationPrecisionWhenOrientationAware) {
6637 static const std::map<ui::Rotation /*rotation*/, std::array<vec2, 4> /*mappedCorners*/>
6638 kMappedCorners = {
6639 {ui::ROTATION_0, {{{0, 0}, {479.5, 0}, {479.5, 799.75}, {0, 799.75}}}},
6640 {ui::ROTATION_90, {{{0.5, 0}, {480, 0}, {480, 799.75}, {0.5, 799.75}}}},
6641 {ui::ROTATION_180, {{{0.5, 0.25}, {480, 0.25}, {480, 800}, {0.5, 800}}}},
6642 {ui::ROTATION_270, {{{0, 0.25}, {479.5, 0.25}, {479.5, 800}, {0, 800}}}},
6643 };
6644
6645 const ui::Rotation displayRotation = GetParam();
6646
6647 addConfigurationProperty("touch.deviceType", "touchScreen");
6648 prepareDisplay(displayRotation);
6649
Arpit Singha8c236b2023-04-25 13:56:05 +00006650 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan82687402022-12-06 01:32:53 +00006651
6652 const auto& expectedPoints = kMappedCorners.at(displayRotation);
6653
6654 // Test all four corners.
6655 for (int i = 0; i < 4; i++) {
6656 const auto& expected = expectedPoints[i];
6657 const auto& raw = kRawCorners[i];
6658 processDown(mapper, raw.x, raw.y);
6659 processSync(mapper);
6660 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6661 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6662 WithCoords(expected.x, expected.y), WithPrecision(2, 4))))
6663 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6664 << "with display rotation " << ui::toCString(displayRotation)
6665 << ", expected point (" << expected.x << ", " << expected.y << ").";
6666 processUp(mapper);
6667 processSync(mapper);
6668 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6669 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6670 WithCoords(expected.x, expected.y))));
6671 }
6672}
6673
Prabir Pradhan3e798762022-12-02 21:02:11 +00006674TEST_P(TouchscreenPrecisionTestsFixture, RotationPrecisionOrientationAwareInOri270) {
6675 static const std::map<ui::Rotation /*orientation*/, std::array<vec2, 4> /*mappedCorners*/>
6676 kMappedCorners = {
6677 {ui::ROTATION_0, {{{799.75, 0}, {799.75, 479.5}, {0, 479.5}, {0, 0}}}},
6678 {ui::ROTATION_90, {{{800, 0}, {800, 479.5}, {0.25, 479.5}, {0.25, 0}}}},
6679 {ui::ROTATION_180, {{{800, 0.5}, {800, 480}, {0.25, 480}, {0.25, 0.5}}}},
6680 {ui::ROTATION_270, {{{799.75, 0.5}, {799.75, 480}, {0, 480}, {0, 0.5}}}},
6681 };
6682
6683 const ui::Rotation displayRotation = GetParam();
6684
6685 addConfigurationProperty("touch.deviceType", "touchScreen");
6686 addConfigurationProperty("touch.orientation", "ORIENTATION_270");
6687
Arpit Singha8c236b2023-04-25 13:56:05 +00006688 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan3e798762022-12-02 21:02:11 +00006689
6690 // Ori 270, so width and height swapped
6691 const Rect physicalFrame{0, 0, DISPLAY_HEIGHT, DISPLAY_WIDTH};
6692 prepareDisplay(displayRotation);
6693 configurePhysicalDisplay(displayRotation, physicalFrame, DISPLAY_HEIGHT, DISPLAY_WIDTH);
6694
6695 const auto& expectedPoints = kMappedCorners.at(displayRotation);
6696
6697 // Test all four corners.
6698 for (int i = 0; i < 4; i++) {
6699 const auto& expected = expectedPoints[i];
6700 const auto& raw = kRawCorners[i];
6701 processDown(mapper, raw.x, raw.y);
6702 processSync(mapper);
6703 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6704 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6705 WithCoords(expected.x, expected.y), WithPrecision(4, 2))))
6706 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6707 << "with display rotation " << ui::toCString(displayRotation)
6708 << ", expected point (" << expected.x << ", " << expected.y << ").";
6709 processUp(mapper);
6710 processSync(mapper);
6711 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6712 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6713 WithCoords(expected.x, expected.y))));
6714 }
6715}
6716
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006717TEST_P(TouchscreenPrecisionTestsFixture, MotionRangesAreOrientedInRotatedDisplay) {
6718 const ui::Rotation displayRotation = GetParam();
6719
6720 addConfigurationProperty("touch.deviceType", "touchScreen");
6721 prepareDisplay(displayRotation);
6722
6723 __attribute__((unused)) SingleTouchInputMapper& mapper =
Arpit Singha8c236b2023-04-25 13:56:05 +00006724 constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006725
6726 const InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
6727 // MotionRanges use display pixels as their units
6728 const auto* xRange = deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHSCREEN);
6729 const auto* yRange = deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_Y, AINPUT_SOURCE_TOUCHSCREEN);
6730
6731 // The MotionRanges should be oriented in the rotated display's coordinate space
6732 const bool displayRotated =
6733 displayRotation == ui::ROTATION_90 || displayRotation == ui::ROTATION_270;
6734
6735 constexpr float MAX_X = 479.5;
6736 constexpr float MAX_Y = 799.75;
6737 EXPECT_EQ(xRange->min, 0.f);
6738 EXPECT_EQ(yRange->min, 0.f);
6739 EXPECT_EQ(xRange->max, displayRotated ? MAX_Y : MAX_X);
6740 EXPECT_EQ(yRange->max, displayRotated ? MAX_X : MAX_Y);
6741
6742 EXPECT_EQ(xRange->flat, 8.f);
6743 EXPECT_EQ(yRange->flat, 8.f);
6744
6745 EXPECT_EQ(xRange->fuzz, 2.f);
6746 EXPECT_EQ(yRange->fuzz, 2.f);
6747
6748 EXPECT_EQ(xRange->resolution, 25.f); // pixels per millimeter
6749 EXPECT_EQ(yRange->resolution, 25.f); // pixels per millimeter
6750}
6751
Prabir Pradhana9df3162022-12-05 23:57:27 +00006752// Run the precision tests for all rotations.
6753INSTANTIATE_TEST_SUITE_P(TouchscreenPrecisionTests, TouchscreenPrecisionTestsFixture,
6754 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
6755 ui::ROTATION_270),
6756 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
6757 return ftl::enum_string(testParamInfo.param);
6758 });
6759
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006760// --- ExternalStylusFusionTest ---
6761
6762class ExternalStylusFusionTest : public SingleTouchInputMapperTest {
6763public:
6764 SingleTouchInputMapper& initializeInputMapperWithExternalStylus() {
6765 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006766 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006767 prepareButtons();
6768 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006769 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006770
6771 mStylusState.when = ARBITRARY_TIME;
6772 mStylusState.pressure = 0.f;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006773 mStylusState.toolType = ToolType::STYLUS;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006774 mReader->getContext()->setExternalStylusDevices({mExternalStylusDeviceInfo});
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006775 configureDevice(InputReaderConfiguration::Change::EXTERNAL_STYLUS_PRESENCE);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006776 processExternalStylusState(mapper);
6777 return mapper;
6778 }
6779
6780 std::list<NotifyArgs> processExternalStylusState(InputMapper& mapper) {
6781 std::list<NotifyArgs> generatedArgs = mapper.updateExternalStylusState(mStylusState);
6782 for (const NotifyArgs& args : generatedArgs) {
6783 mFakeListener->notify(args);
6784 }
6785 // Loop the reader to flush the input listener queue.
6786 mReader->loopOnce();
6787 return generatedArgs;
6788 }
6789
6790protected:
6791 StylusState mStylusState{};
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006792
6793 void testStartFusedStylusGesture(SingleTouchInputMapper& mapper) {
6794 auto toolTypeSource =
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006795 AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006796
6797 // The first pointer is withheld.
6798 processDown(mapper, 100, 200);
6799 processSync(mapper);
6800 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6801 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6802 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6803
6804 // The external stylus reports pressure. The withheld finger pointer is released as a
6805 // stylus.
6806 mStylusState.pressure = 1.f;
6807 processExternalStylusState(mapper);
6808 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6809 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6810 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6811
6812 // Subsequent pointer events are not withheld.
6813 processMove(mapper, 101, 201);
6814 processSync(mapper);
6815 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6816 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6817
6818 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6819 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6820 }
6821
6822 void testSuccessfulFusionGesture(SingleTouchInputMapper& mapper) {
6823 ASSERT_NO_FATAL_FAILURE(testStartFusedStylusGesture(mapper));
6824
6825 // Releasing the touch pointer ends the gesture.
6826 processUp(mapper);
6827 processSync(mapper);
6828 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006829 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(STYLUS_FUSION_SOURCE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006830 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006831
6832 mStylusState.pressure = 0.f;
6833 processExternalStylusState(mapper);
6834 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6835 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6836 }
6837
6838 void testUnsuccessfulFusionGesture(SingleTouchInputMapper& mapper) {
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006839 // When stylus fusion is not successful, events should be reported with the original source.
6840 // In this case, it is from a touchscreen.
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006841 auto toolTypeSource =
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006842 AllOf(WithSource(AINPUT_SOURCE_TOUCHSCREEN), WithToolType(ToolType::FINGER));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006843
6844 // The first pointer is withheld when an external stylus is connected,
6845 // and a timeout is requested.
6846 processDown(mapper, 100, 200);
6847 processSync(mapper);
6848 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6849 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6850 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6851
6852 // If the timeout expires early, it is requested again.
6853 handleTimeout(mapper, ARBITRARY_TIME + 1);
6854 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6855 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6856
6857 // When the timeout expires, the withheld touch is released as a finger pointer.
6858 handleTimeout(mapper, ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT);
6859 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6860 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6861
6862 // Subsequent pointer events are not withheld.
6863 processMove(mapper, 101, 201);
6864 processSync(mapper);
6865 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6866 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6867 processUp(mapper);
6868 processSync(mapper);
6869 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6870 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP))));
6871
6872 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6873 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6874 }
6875
6876private:
6877 InputDeviceInfo mExternalStylusDeviceInfo{};
6878};
6879
6880TEST_F(ExternalStylusFusionTest, UsesBluetoothStylusSource) {
6881 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006882 ASSERT_EQ(STYLUS_FUSION_SOURCE, mapper.getSources());
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006883}
6884
6885TEST_F(ExternalStylusFusionTest, UnsuccessfulFusion) {
6886 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6887 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6888}
6889
6890TEST_F(ExternalStylusFusionTest, SuccessfulFusion_TouchFirst) {
6891 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6892 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6893}
6894
6895// Test a successful stylus fusion gesture where the pressure is reported by the external
6896// before the touch is reported by the touchscreen.
6897TEST_F(ExternalStylusFusionTest, SuccessfulFusion_PressureFirst) {
6898 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006899 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006900
6901 // The external stylus reports pressure first. It is ignored for now.
6902 mStylusState.pressure = 1.f;
6903 processExternalStylusState(mapper);
6904 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6905 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6906
6907 // When the touch goes down afterwards, it is reported as a stylus pointer.
6908 processDown(mapper, 100, 200);
6909 processSync(mapper);
6910 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6911 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6912 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6913
6914 processMove(mapper, 101, 201);
6915 processSync(mapper);
6916 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6917 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6918 processUp(mapper);
6919 processSync(mapper);
6920 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6921 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP))));
6922
6923 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6924 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6925}
6926
6927TEST_F(ExternalStylusFusionTest, FusionIsRepeatedForEachNewGesture) {
6928 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6929
6930 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6931 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6932
6933 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6934 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6935 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6936 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6937}
6938
6939TEST_F(ExternalStylusFusionTest, FusedPointerReportsPressureChanges) {
6940 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006941 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006942
6943 mStylusState.pressure = 0.8f;
6944 processExternalStylusState(mapper);
6945 processDown(mapper, 100, 200);
6946 processSync(mapper);
6947 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6948 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6949 WithPressure(0.8f))));
6950 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6951
6952 // The external stylus reports a pressure change. We wait for some time for a touch event.
6953 mStylusState.pressure = 0.6f;
6954 processExternalStylusState(mapper);
6955 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6956 ASSERT_NO_FATAL_FAILURE(
6957 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6958
6959 // If a touch is reported within the timeout, it reports the updated pressure.
6960 processMove(mapper, 101, 201);
6961 processSync(mapper);
6962 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6963 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6964 WithPressure(0.6f))));
6965 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6966
6967 // There is another pressure change.
6968 mStylusState.pressure = 0.5f;
6969 processExternalStylusState(mapper);
6970 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6971 ASSERT_NO_FATAL_FAILURE(
6972 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6973
6974 // If a touch is not reported within the timeout, a move event is generated to report
6975 // the new pressure.
6976 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
6977 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6978 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6979 WithPressure(0.5f))));
6980
6981 // If a zero pressure is reported before the touch goes up, the previous pressure value is
6982 // repeated indefinitely.
6983 mStylusState.pressure = 0.0f;
6984 processExternalStylusState(mapper);
6985 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6986 ASSERT_NO_FATAL_FAILURE(
6987 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6988 processMove(mapper, 102, 202);
6989 processSync(mapper);
6990 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6991 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6992 WithPressure(0.5f))));
6993 processMove(mapper, 103, 203);
6994 processSync(mapper);
6995 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6996 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6997 WithPressure(0.5f))));
6998
6999 processUp(mapper);
7000 processSync(mapper);
7001 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00007002 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(STYLUS_FUSION_SOURCE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007003 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007004
7005 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7006 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7007}
7008
7009TEST_F(ExternalStylusFusionTest, FusedPointerReportsToolTypeChanges) {
7010 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00007011 auto source = WithSource(STYLUS_FUSION_SOURCE);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007012
7013 mStylusState.pressure = 1.f;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007014 mStylusState.toolType = ToolType::ERASER;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007015 processExternalStylusState(mapper);
7016 processDown(mapper, 100, 200);
7017 processSync(mapper);
7018 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7019 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007020 WithToolType(ToolType::ERASER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007021 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7022
7023 // The external stylus reports a tool change. We wait for some time for a touch event.
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007024 mStylusState.toolType = ToolType::STYLUS;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007025 processExternalStylusState(mapper);
7026 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7027 ASSERT_NO_FATAL_FAILURE(
7028 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7029
7030 // If a touch is reported within the timeout, it reports the updated pressure.
7031 processMove(mapper, 101, 201);
7032 processSync(mapper);
7033 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7034 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007035 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007036 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7037
7038 // There is another tool type change.
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007039 mStylusState.toolType = ToolType::FINGER;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007040 processExternalStylusState(mapper);
7041 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7042 ASSERT_NO_FATAL_FAILURE(
7043 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7044
7045 // If a touch is not reported within the timeout, a move event is generated to report
7046 // the new tool type.
7047 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
7048 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7049 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007050 WithToolType(ToolType::FINGER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007051
7052 processUp(mapper);
7053 processSync(mapper);
7054 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7055 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007056 WithToolType(ToolType::FINGER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007057
7058 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7059 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7060}
7061
7062TEST_F(ExternalStylusFusionTest, FusedPointerReportsButtons) {
7063 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00007064 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007065
7066 ASSERT_NO_FATAL_FAILURE(testStartFusedStylusGesture(mapper));
7067
7068 // The external stylus reports a button change. We wait for some time for a touch event.
7069 mStylusState.buttons = AMOTION_EVENT_BUTTON_STYLUS_PRIMARY;
7070 processExternalStylusState(mapper);
7071 ASSERT_NO_FATAL_FAILURE(
7072 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7073
7074 // If a touch is reported within the timeout, it reports the updated button state.
7075 processMove(mapper, 101, 201);
7076 processSync(mapper);
7077 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7078 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
7079 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
7080 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7081 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
7082 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
7083 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7084
7085 // The button is now released.
7086 mStylusState.buttons = 0;
7087 processExternalStylusState(mapper);
7088 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7089 ASSERT_NO_FATAL_FAILURE(
7090 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7091
7092 // If a touch is not reported within the timeout, a move event is generated to report
7093 // the new button state.
7094 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007095 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7096 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
7097 WithButtonState(0))));
7098 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhan124ea442022-10-28 20:27:44 +00007099 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
7100 WithButtonState(0))));
7101
7102 processUp(mapper);
7103 processSync(mapper);
7104 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007105 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
7106
7107 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7108 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7109}
7110
Michael Wrightd02c5b62014-02-10 15:10:22 -08007111// --- MultiTouchInputMapperTest ---
7112
7113class MultiTouchInputMapperTest : public TouchInputMapperTest {
7114protected:
7115 void prepareAxes(int axes);
7116
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007117 void processPosition(MultiTouchInputMapper& mapper, int32_t x, int32_t y);
7118 void processTouchMajor(MultiTouchInputMapper& mapper, int32_t touchMajor);
7119 void processTouchMinor(MultiTouchInputMapper& mapper, int32_t touchMinor);
7120 void processToolMajor(MultiTouchInputMapper& mapper, int32_t toolMajor);
7121 void processToolMinor(MultiTouchInputMapper& mapper, int32_t toolMinor);
7122 void processOrientation(MultiTouchInputMapper& mapper, int32_t orientation);
7123 void processPressure(MultiTouchInputMapper& mapper, int32_t pressure);
7124 void processDistance(MultiTouchInputMapper& mapper, int32_t distance);
7125 void processId(MultiTouchInputMapper& mapper, int32_t id);
7126 void processSlot(MultiTouchInputMapper& mapper, int32_t slot);
7127 void processToolType(MultiTouchInputMapper& mapper, int32_t toolType);
7128 void processKey(MultiTouchInputMapper& mapper, int32_t code, int32_t value);
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00007129 void processHidUsage(MultiTouchInputMapper& mapper, int32_t usageCode, int32_t value);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007130 void processMTSync(MultiTouchInputMapper& mapper);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00007131 void processSync(MultiTouchInputMapper& mapper, nsecs_t eventTime = ARBITRARY_TIME,
7132 nsecs_t readTime = READ_TIME);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007133};
7134
7135void MultiTouchInputMapperTest::prepareAxes(int axes) {
7136 if (axes & POSITION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007137 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
7138 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007139 }
7140 if (axes & TOUCH) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007141 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN,
7142 RAW_TOUCH_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007143 if (axes & MINOR) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007144 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN,
7145 RAW_TOUCH_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007146 }
7147 }
7148 if (axes & TOOL) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007149 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7150 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007151 if (axes & MINOR) {
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007152 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MIN,
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007153 RAW_TOOL_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007154 }
7155 }
7156 if (axes & ORIENTATION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007157 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_ORIENTATION, RAW_ORIENTATION_MIN,
7158 RAW_ORIENTATION_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007159 }
7160 if (axes & PRESSURE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007161 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_PRESSURE, RAW_PRESSURE_MIN,
7162 RAW_PRESSURE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007163 }
7164 if (axes & DISTANCE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007165 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_DISTANCE, RAW_DISTANCE_MIN,
7166 RAW_DISTANCE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007167 }
7168 if (axes & ID) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007169 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TRACKING_ID, RAW_ID_MIN, RAW_ID_MAX, 0,
7170 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007171 }
7172 if (axes & SLOT) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007173 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_SLOT, RAW_SLOT_MIN, RAW_SLOT_MAX, 0, 0);
7174 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007175 }
7176 if (axes & TOOL_TYPE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007177 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007178 }
7179}
7180
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007181void MultiTouchInputMapperTest::processPosition(MultiTouchInputMapper& mapper, int32_t x,
7182 int32_t y) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007183 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
7184 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007185}
7186
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007187void MultiTouchInputMapperTest::processTouchMajor(MultiTouchInputMapper& mapper,
7188 int32_t touchMajor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007189 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOUCH_MAJOR, touchMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007190}
7191
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007192void MultiTouchInputMapperTest::processTouchMinor(MultiTouchInputMapper& mapper,
7193 int32_t touchMinor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007194 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOUCH_MINOR, touchMinor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007195}
7196
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007197void MultiTouchInputMapperTest::processToolMajor(MultiTouchInputMapper& mapper, int32_t toolMajor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007198 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_WIDTH_MAJOR, toolMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007199}
7200
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007201void MultiTouchInputMapperTest::processToolMinor(MultiTouchInputMapper& mapper, int32_t toolMinor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007202 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_WIDTH_MINOR, toolMinor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007203}
7204
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007205void MultiTouchInputMapperTest::processOrientation(MultiTouchInputMapper& mapper,
7206 int32_t orientation) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007207 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_ORIENTATION, orientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007208}
7209
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007210void MultiTouchInputMapperTest::processPressure(MultiTouchInputMapper& mapper, int32_t pressure) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007211 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_PRESSURE, pressure);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007212}
7213
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007214void MultiTouchInputMapperTest::processDistance(MultiTouchInputMapper& mapper, int32_t distance) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007215 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_DISTANCE, distance);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007216}
7217
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007218void MultiTouchInputMapperTest::processId(MultiTouchInputMapper& mapper, int32_t id) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007219 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TRACKING_ID, id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007220}
7221
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007222void MultiTouchInputMapperTest::processSlot(MultiTouchInputMapper& mapper, int32_t slot) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007223 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_SLOT, slot);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007224}
7225
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007226void MultiTouchInputMapperTest::processToolType(MultiTouchInputMapper& mapper, int32_t toolType) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007227 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOOL_TYPE, toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007228}
7229
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007230void MultiTouchInputMapperTest::processKey(MultiTouchInputMapper& mapper, int32_t code,
7231 int32_t value) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007232 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007233}
7234
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00007235void MultiTouchInputMapperTest::processHidUsage(MultiTouchInputMapper& mapper, int32_t usageCode,
7236 int32_t value) {
7237 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, usageCode);
7238 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, value);
7239}
7240
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007241void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper& mapper) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007242 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_MT_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007243}
7244
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00007245void MultiTouchInputMapperTest::processSync(MultiTouchInputMapper& mapper, nsecs_t eventTime,
7246 nsecs_t readTime) {
7247 process(mapper, eventTime, readTime, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007248}
7249
Michael Wrightd02c5b62014-02-10 15:10:22 -08007250TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackingIds) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007251 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007252 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007253 prepareAxes(POSITION);
7254 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007255 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007256
arthurhungdcef2dc2020-08-11 14:47:50 +08007257 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007258
7259 NotifyMotionArgs motionArgs;
7260
7261 // Two fingers down at once.
7262 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7263 processPosition(mapper, x1, y1);
7264 processMTSync(mapper);
7265 processPosition(mapper, x2, y2);
7266 processMTSync(mapper);
7267 processSync(mapper);
7268
7269 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7270 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7271 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7272 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7273 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7274 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
7275 ASSERT_EQ(0, motionArgs.flags);
7276 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7277 ASSERT_EQ(0, motionArgs.buttonState);
7278 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007279 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007280 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007281 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007282 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7283 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7284 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7285 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7286 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7287
7288 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7289 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7290 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7291 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7292 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007293 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007294 ASSERT_EQ(0, motionArgs.flags);
7295 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7296 ASSERT_EQ(0, motionArgs.buttonState);
7297 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007298 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007299 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007300 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007301 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007302 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007303 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7304 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7305 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7306 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7307 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7308 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7309 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7310
7311 // Move.
7312 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7313 processPosition(mapper, x1, y1);
7314 processMTSync(mapper);
7315 processPosition(mapper, x2, y2);
7316 processMTSync(mapper);
7317 processSync(mapper);
7318
7319 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7320 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7321 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7322 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7323 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7324 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7325 ASSERT_EQ(0, motionArgs.flags);
7326 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7327 ASSERT_EQ(0, motionArgs.buttonState);
7328 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007329 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007330 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007331 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007332 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007333 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007334 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7335 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7336 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7337 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7338 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7339 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7340 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7341
7342 // First finger up.
7343 x2 += 15; y2 -= 20;
7344 processPosition(mapper, x2, y2);
7345 processMTSync(mapper);
7346 processSync(mapper);
7347
7348 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7349 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7350 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7351 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7352 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007353 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007354 ASSERT_EQ(0, motionArgs.flags);
7355 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7356 ASSERT_EQ(0, motionArgs.buttonState);
7357 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007358 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007359 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007360 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007361 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007362 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007363 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7364 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7365 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7366 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7367 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7368 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7369 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7370
7371 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7372 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7373 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7374 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7375 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7376 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7377 ASSERT_EQ(0, motionArgs.flags);
7378 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7379 ASSERT_EQ(0, motionArgs.buttonState);
7380 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007381 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007382 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007383 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007384 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7385 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7386 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7387 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7388 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7389
7390 // Move.
7391 x2 += 20; y2 -= 25;
7392 processPosition(mapper, x2, y2);
7393 processMTSync(mapper);
7394 processSync(mapper);
7395
7396 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7397 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7398 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7399 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7400 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7401 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7402 ASSERT_EQ(0, motionArgs.flags);
7403 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7404 ASSERT_EQ(0, motionArgs.buttonState);
7405 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007406 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007407 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007408 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007409 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7410 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7411 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7412 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7413 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7414
7415 // New finger down.
7416 int32_t x3 = 700, y3 = 300;
7417 processPosition(mapper, x2, y2);
7418 processMTSync(mapper);
7419 processPosition(mapper, x3, y3);
7420 processMTSync(mapper);
7421 processSync(mapper);
7422
7423 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7424 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7425 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7426 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7427 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007428 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007429 ASSERT_EQ(0, motionArgs.flags);
7430 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7431 ASSERT_EQ(0, motionArgs.buttonState);
7432 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007433 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007434 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007435 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007436 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007437 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007438 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7439 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7440 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7441 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7442 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7443 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7444 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7445
7446 // Second finger up.
7447 x3 += 30; y3 -= 20;
7448 processPosition(mapper, x3, y3);
7449 processMTSync(mapper);
7450 processSync(mapper);
7451
7452 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7453 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7454 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7455 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7456 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007457 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007458 ASSERT_EQ(0, motionArgs.flags);
7459 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7460 ASSERT_EQ(0, motionArgs.buttonState);
7461 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007462 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007463 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007464 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007465 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007466 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007467 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7468 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7469 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7470 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7471 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7472 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7473 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7474
7475 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7476 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7477 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7478 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7479 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7480 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7481 ASSERT_EQ(0, motionArgs.flags);
7482 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7483 ASSERT_EQ(0, motionArgs.buttonState);
7484 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007485 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007486 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007487 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007488 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7489 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7490 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7491 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7492 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7493
7494 // Last finger up.
7495 processMTSync(mapper);
7496 processSync(mapper);
7497
7498 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7499 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7500 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7501 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7502 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7503 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
7504 ASSERT_EQ(0, motionArgs.flags);
7505 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7506 ASSERT_EQ(0, motionArgs.buttonState);
7507 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007508 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007509 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007510 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007511 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7512 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7513 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7514 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7515 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7516
7517 // Should not have sent any more keys or motions.
7518 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7519 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7520}
7521
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007522TEST_F(MultiTouchInputMapperTest, AxisResolution_IsPopulated) {
7523 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007524 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007525
7526 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, /*flat*/ 0,
7527 /*fuzz*/ 0, /*resolution*/ 10);
7528 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, /*flat*/ 0,
7529 /*fuzz*/ 0, /*resolution*/ 11);
7530 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX,
7531 /*flat*/ 0, /*fuzz*/ 0, /*resolution*/ 12);
7532 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX,
7533 /*flat*/ 0, /*fuzz*/ 0, /*resolution*/ 13);
7534 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7535 /*flat*/ 0, /*flat*/ 0, /*resolution*/ 14);
7536 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7537 /*flat*/ 0, /*flat*/ 0, /*resolution*/ 15);
7538
Arpit Singha8c236b2023-04-25 13:56:05 +00007539 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007540
7541 // X and Y axes
7542 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_X, 10 / X_PRECISION);
7543 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_Y, 11 / Y_PRECISION);
7544 // Touch major and minor
7545 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOUCH_MAJOR, 12 * GEOMETRIC_SCALE);
7546 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOUCH_MINOR, 13 * GEOMETRIC_SCALE);
7547 // Tool major and minor
7548 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOOL_MAJOR, 14 * GEOMETRIC_SCALE);
7549 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOOL_MINOR, 15 * GEOMETRIC_SCALE);
7550}
7551
7552TEST_F(MultiTouchInputMapperTest, TouchMajorAndMinorAxes_DoNotAppearIfNotSupported) {
7553 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007554 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007555
7556 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, /*flat*/ 0,
7557 /*fuzz*/ 0, /*resolution*/ 10);
7558 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, /*flat*/ 0,
7559 /*fuzz*/ 0, /*resolution*/ 11);
7560
7561 // We do not add ABS_MT_TOUCH_MAJOR / MINOR or ABS_MT_WIDTH_MAJOR / MINOR axes
7562
Arpit Singha8c236b2023-04-25 13:56:05 +00007563 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007564
7565 // Touch major and minor
7566 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOUCH_MAJOR);
7567 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOUCH_MINOR);
7568 // Tool major and minor
7569 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOOL_MAJOR);
7570 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOOL_MINOR);
7571}
7572
Michael Wrightd02c5b62014-02-10 15:10:22 -08007573TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingIds) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007574 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007575 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007576 prepareAxes(POSITION | ID);
7577 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007578 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007579
arthurhungdcef2dc2020-08-11 14:47:50 +08007580 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007581
7582 NotifyMotionArgs motionArgs;
7583
7584 // Two fingers down at once.
7585 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7586 processPosition(mapper, x1, y1);
7587 processId(mapper, 1);
7588 processMTSync(mapper);
7589 processPosition(mapper, x2, y2);
7590 processId(mapper, 2);
7591 processMTSync(mapper);
7592 processSync(mapper);
7593
7594 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7595 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007596 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007597 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007598 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].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
7602 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007603 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007604 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007605 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007606 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007607 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007608 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007609 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7610 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7611 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7612 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7613
7614 // Move.
7615 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7616 processPosition(mapper, x1, y1);
7617 processId(mapper, 1);
7618 processMTSync(mapper);
7619 processPosition(mapper, x2, y2);
7620 processId(mapper, 2);
7621 processMTSync(mapper);
7622 processSync(mapper);
7623
7624 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7625 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007626 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007627 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007628 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007629 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007630 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007631 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7632 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7633 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7634 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7635
7636 // First finger up.
7637 x2 += 15; y2 -= 20;
7638 processPosition(mapper, x2, y2);
7639 processId(mapper, 2);
7640 processMTSync(mapper);
7641 processSync(mapper);
7642
7643 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007644 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007645 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007646 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007647 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007648 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007649 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007650 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7651 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7652 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7653 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7654
7655 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7656 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007657 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007658 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007659 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007660 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7661 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7662
7663 // Move.
7664 x2 += 20; y2 -= 25;
7665 processPosition(mapper, x2, y2);
7666 processId(mapper, 2);
7667 processMTSync(mapper);
7668 processSync(mapper);
7669
7670 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7671 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007672 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007673 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007674 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007675 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7676 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7677
7678 // New finger down.
7679 int32_t x3 = 700, y3 = 300;
7680 processPosition(mapper, x2, y2);
7681 processId(mapper, 2);
7682 processMTSync(mapper);
7683 processPosition(mapper, x3, y3);
7684 processId(mapper, 3);
7685 processMTSync(mapper);
7686 processSync(mapper);
7687
7688 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007689 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007690 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007691 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007692 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007693 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007694 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007695 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7696 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7697 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7698 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7699
7700 // Second finger up.
7701 x3 += 30; y3 -= 20;
7702 processPosition(mapper, x3, y3);
7703 processId(mapper, 3);
7704 processMTSync(mapper);
7705 processSync(mapper);
7706
7707 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007708 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007709 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007710 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007711 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007712 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007713 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007714 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7715 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7716 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7717 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7718
7719 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7720 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007721 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007722 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007723 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007724 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7725 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7726
7727 // Last finger up.
7728 processMTSync(mapper);
7729 processSync(mapper);
7730
7731 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7732 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007733 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007734 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007735 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007736 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7737 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7738
7739 // Should not have sent any more keys or motions.
7740 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7741 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7742}
7743
7744TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithSlots) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007745 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007746 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007747 prepareAxes(POSITION | ID | SLOT);
7748 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007749 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007750
arthurhungdcef2dc2020-08-11 14:47:50 +08007751 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007752
7753 NotifyMotionArgs motionArgs;
7754
7755 // Two fingers down at once.
7756 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7757 processPosition(mapper, x1, y1);
7758 processId(mapper, 1);
7759 processSlot(mapper, 1);
7760 processPosition(mapper, x2, y2);
7761 processId(mapper, 2);
7762 processSync(mapper);
7763
7764 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7765 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007766 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007767 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007768 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007769 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7770 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7771
7772 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007773 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007774 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007775 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007776 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007777 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007778 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007779 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7780 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7781 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7782 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7783
7784 // Move.
7785 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7786 processSlot(mapper, 0);
7787 processPosition(mapper, x1, y1);
7788 processSlot(mapper, 1);
7789 processPosition(mapper, x2, y2);
7790 processSync(mapper);
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(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007795 ASSERT_EQ(0, 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_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007798 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007799 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7800 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7801 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7802 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7803
7804 // First finger up.
7805 x2 += 15; y2 -= 20;
7806 processSlot(mapper, 0);
7807 processId(mapper, -1);
7808 processSlot(mapper, 1);
7809 processPosition(mapper, x2, y2);
7810 processSync(mapper);
7811
7812 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007813 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007814 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007815 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007816 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007817 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007818 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007819 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7820 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7821 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7822 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7823
7824 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7825 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007826 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007827 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007828 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007829 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7830 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7831
7832 // Move.
7833 x2 += 20; y2 -= 25;
7834 processPosition(mapper, x2, y2);
7835 processSync(mapper);
7836
7837 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7838 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007839 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007840 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007841 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007842 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7843 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7844
7845 // New finger down.
7846 int32_t x3 = 700, y3 = 300;
7847 processPosition(mapper, x2, y2);
7848 processSlot(mapper, 0);
7849 processId(mapper, 3);
7850 processPosition(mapper, x3, y3);
7851 processSync(mapper);
7852
7853 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007854 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007855 ASSERT_EQ(size_t(2), 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_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007859 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007860 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7861 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7862 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7863 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7864
7865 // Second finger up.
7866 x3 += 30; y3 -= 20;
7867 processSlot(mapper, 1);
7868 processId(mapper, -1);
7869 processSlot(mapper, 0);
7870 processPosition(mapper, x3, y3);
7871 processSync(mapper);
7872
7873 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007874 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007875 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007876 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007877 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007878 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007879 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007880 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7881 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7882 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7883 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7884
7885 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7886 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007887 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007888 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007889 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007890 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7891 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7892
7893 // Last finger up.
7894 processId(mapper, -1);
7895 processSync(mapper);
7896
7897 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7898 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007899 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007900 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007901 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007902 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7903 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7904
7905 // Should not have sent any more keys or motions.
7906 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7907 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7908}
7909
7910TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007911 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007912 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007913 prepareAxes(POSITION | TOUCH | TOOL | PRESSURE | ORIENTATION | ID | MINOR | DISTANCE);
Arpit Singha8c236b2023-04-25 13:56:05 +00007914 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007915
7916 // These calculations are based on the input device calibration documentation.
7917 int32_t rawX = 100;
7918 int32_t rawY = 200;
7919 int32_t rawTouchMajor = 7;
7920 int32_t rawTouchMinor = 6;
7921 int32_t rawToolMajor = 9;
7922 int32_t rawToolMinor = 8;
7923 int32_t rawPressure = 11;
7924 int32_t rawDistance = 0;
7925 int32_t rawOrientation = 3;
7926 int32_t id = 5;
7927
7928 float x = toDisplayX(rawX);
7929 float y = toDisplayY(rawY);
7930 float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
7931 float size = avg(rawTouchMajor, rawTouchMinor) / RAW_TOUCH_MAX;
7932 float toolMajor = float(rawToolMajor) * GEOMETRIC_SCALE;
7933 float toolMinor = float(rawToolMinor) * GEOMETRIC_SCALE;
7934 float touchMajor = float(rawTouchMajor) * GEOMETRIC_SCALE;
7935 float touchMinor = float(rawTouchMinor) * GEOMETRIC_SCALE;
7936 float orientation = float(rawOrientation) / RAW_ORIENTATION_MAX * M_PI_2;
7937 float distance = float(rawDistance);
7938
7939 processPosition(mapper, rawX, rawY);
7940 processTouchMajor(mapper, rawTouchMajor);
7941 processTouchMinor(mapper, rawTouchMinor);
7942 processToolMajor(mapper, rawToolMajor);
7943 processToolMinor(mapper, rawToolMinor);
7944 processPressure(mapper, rawPressure);
7945 processOrientation(mapper, rawOrientation);
7946 processDistance(mapper, rawDistance);
7947 processId(mapper, id);
7948 processMTSync(mapper);
7949 processSync(mapper);
7950
7951 NotifyMotionArgs args;
7952 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7953 ASSERT_EQ(0, args.pointerProperties[0].id);
7954 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7955 x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor,
7956 orientation, distance));
7957}
7958
7959TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_GeometricCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007960 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007961 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007962 prepareAxes(POSITION | TOUCH | TOOL | MINOR);
7963 addConfigurationProperty("touch.size.calibration", "geometric");
Arpit Singha8c236b2023-04-25 13:56:05 +00007964 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007965
7966 // These calculations are based on the input device calibration documentation.
7967 int32_t rawX = 100;
7968 int32_t rawY = 200;
7969 int32_t rawTouchMajor = 140;
7970 int32_t rawTouchMinor = 120;
7971 int32_t rawToolMajor = 180;
7972 int32_t rawToolMinor = 160;
7973
7974 float x = toDisplayX(rawX);
7975 float y = toDisplayY(rawY);
7976 float size = avg(rawTouchMajor, rawTouchMinor) / RAW_TOUCH_MAX;
7977 float toolMajor = float(rawToolMajor) * GEOMETRIC_SCALE;
7978 float toolMinor = float(rawToolMinor) * GEOMETRIC_SCALE;
7979 float touchMajor = float(rawTouchMajor) * GEOMETRIC_SCALE;
7980 float touchMinor = float(rawTouchMinor) * GEOMETRIC_SCALE;
7981
7982 processPosition(mapper, rawX, rawY);
7983 processTouchMajor(mapper, rawTouchMajor);
7984 processTouchMinor(mapper, rawTouchMinor);
7985 processToolMajor(mapper, rawToolMajor);
7986 processToolMinor(mapper, rawToolMinor);
7987 processMTSync(mapper);
7988 processSync(mapper);
7989
7990 NotifyMotionArgs args;
7991 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7992 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7993 x, y, 1.0f, size, touchMajor, touchMinor, toolMajor, toolMinor, 0, 0));
7994}
7995
7996TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_SummedLinearCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007997 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007998 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007999 prepareAxes(POSITION | TOUCH | TOOL);
8000 addConfigurationProperty("touch.size.calibration", "diameter");
8001 addConfigurationProperty("touch.size.scale", "10");
8002 addConfigurationProperty("touch.size.bias", "160");
8003 addConfigurationProperty("touch.size.isSummed", "1");
Arpit Singha8c236b2023-04-25 13:56:05 +00008004 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008005
8006 // These calculations are based on the input device calibration documentation.
8007 // Note: We only provide a single common touch/tool value because the device is assumed
8008 // not to emit separate values for each pointer (isSummed = 1).
8009 int32_t rawX = 100;
8010 int32_t rawY = 200;
8011 int32_t rawX2 = 150;
8012 int32_t rawY2 = 250;
8013 int32_t rawTouchMajor = 5;
8014 int32_t rawToolMajor = 8;
8015
8016 float x = toDisplayX(rawX);
8017 float y = toDisplayY(rawY);
8018 float x2 = toDisplayX(rawX2);
8019 float y2 = toDisplayY(rawY2);
8020 float size = float(rawTouchMajor) / 2 / RAW_TOUCH_MAX;
8021 float touch = float(rawTouchMajor) / 2 * 10.0f + 160.0f;
8022 float tool = float(rawToolMajor) / 2 * 10.0f + 160.0f;
8023
8024 processPosition(mapper, rawX, rawY);
8025 processTouchMajor(mapper, rawTouchMajor);
8026 processToolMajor(mapper, rawToolMajor);
8027 processMTSync(mapper);
8028 processPosition(mapper, rawX2, rawY2);
8029 processTouchMajor(mapper, rawTouchMajor);
8030 processToolMajor(mapper, rawToolMajor);
8031 processMTSync(mapper);
8032 processSync(mapper);
8033
8034 NotifyMotionArgs args;
8035 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8036 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
8037
8038 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08008039 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07008040 ASSERT_EQ(size_t(2), args.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08008041 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8042 x, y, 1.0f, size, touch, touch, tool, tool, 0, 0));
8043 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[1],
8044 x2, y2, 1.0f, size, touch, touch, tool, tool, 0, 0));
8045}
8046
8047TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_AreaCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008048 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008049 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008050 prepareAxes(POSITION | TOUCH | TOOL);
8051 addConfigurationProperty("touch.size.calibration", "area");
8052 addConfigurationProperty("touch.size.scale", "43");
8053 addConfigurationProperty("touch.size.bias", "3");
Arpit Singha8c236b2023-04-25 13:56:05 +00008054 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008055
8056 // These calculations are based on the input device calibration documentation.
8057 int32_t rawX = 100;
8058 int32_t rawY = 200;
8059 int32_t rawTouchMajor = 5;
8060 int32_t rawToolMajor = 8;
8061
8062 float x = toDisplayX(rawX);
8063 float y = toDisplayY(rawY);
8064 float size = float(rawTouchMajor) / RAW_TOUCH_MAX;
8065 float touch = sqrtf(rawTouchMajor) * 43.0f + 3.0f;
8066 float tool = sqrtf(rawToolMajor) * 43.0f + 3.0f;
8067
8068 processPosition(mapper, rawX, rawY);
8069 processTouchMajor(mapper, rawTouchMajor);
8070 processToolMajor(mapper, rawToolMajor);
8071 processMTSync(mapper);
8072 processSync(mapper);
8073
8074 NotifyMotionArgs args;
8075 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8076 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8077 x, y, 1.0f, size, touch, touch, tool, tool, 0, 0));
8078}
8079
8080TEST_F(MultiTouchInputMapperTest, Process_PressureAxis_AmplitudeCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008081 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008082 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008083 prepareAxes(POSITION | PRESSURE);
8084 addConfigurationProperty("touch.pressure.calibration", "amplitude");
8085 addConfigurationProperty("touch.pressure.scale", "0.01");
Arpit Singha8c236b2023-04-25 13:56:05 +00008086 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008087
Michael Wrightaa449c92017-12-13 21:21:43 +00008088 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +00008089 mapper.populateDeviceInfo(info);
Michael Wrightaa449c92017-12-13 21:21:43 +00008090 ASSERT_NO_FATAL_FAILURE(assertMotionRange(info,
8091 AINPUT_MOTION_RANGE_PRESSURE, AINPUT_SOURCE_TOUCHSCREEN,
8092 0.0f, RAW_PRESSURE_MAX * 0.01, 0.0f, 0.0f));
8093
Michael Wrightd02c5b62014-02-10 15:10:22 -08008094 // These calculations are based on the input device calibration documentation.
8095 int32_t rawX = 100;
8096 int32_t rawY = 200;
8097 int32_t rawPressure = 60;
8098
8099 float x = toDisplayX(rawX);
8100 float y = toDisplayY(rawY);
8101 float pressure = float(rawPressure) * 0.01f;
8102
8103 processPosition(mapper, rawX, rawY);
8104 processPressure(mapper, rawPressure);
8105 processMTSync(mapper);
8106 processSync(mapper);
8107
8108 NotifyMotionArgs args;
8109 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8110 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8111 x, y, pressure, 0, 0, 0, 0, 0, 0, 0));
8112}
8113
8114TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllButtons) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008115 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008116 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008117 prepareAxes(POSITION | ID | SLOT);
Arpit Singha8c236b2023-04-25 13:56:05 +00008118 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008119
8120 NotifyMotionArgs motionArgs;
8121 NotifyKeyArgs keyArgs;
8122
8123 processId(mapper, 1);
8124 processPosition(mapper, 100, 200);
8125 processSync(mapper);
8126 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8127 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8128 ASSERT_EQ(0, motionArgs.buttonState);
8129
8130 // press BTN_LEFT, release BTN_LEFT
8131 processKey(mapper, BTN_LEFT, 1);
8132 processSync(mapper);
8133 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8134 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
8135 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
8136
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008137 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8138 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8139 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
8140
Michael Wrightd02c5b62014-02-10 15:10:22 -08008141 processKey(mapper, BTN_LEFT, 0);
8142 processSync(mapper);
8143 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008144 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008145 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008146
8147 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008148 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008149 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008150
8151 // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
8152 processKey(mapper, BTN_RIGHT, 1);
8153 processKey(mapper, BTN_MIDDLE, 1);
8154 processSync(mapper);
8155 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8156 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
8157 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
8158 motionArgs.buttonState);
8159
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008160 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8161 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8162 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
8163
8164 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8165 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8166 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
8167 motionArgs.buttonState);
8168
Michael Wrightd02c5b62014-02-10 15:10:22 -08008169 processKey(mapper, BTN_RIGHT, 0);
8170 processSync(mapper);
8171 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008172 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008173 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008174
8175 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008176 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008177 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008178
8179 processKey(mapper, BTN_MIDDLE, 0);
8180 processSync(mapper);
8181 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008182 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008183 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008184
8185 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008186 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008187 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008188
8189 // press BTN_BACK, release BTN_BACK
8190 processKey(mapper, BTN_BACK, 1);
8191 processSync(mapper);
8192 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8193 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8194 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008195
Michael Wrightd02c5b62014-02-10 15:10:22 -08008196 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008197 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008198 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
8199
8200 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8201 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8202 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008203
8204 processKey(mapper, BTN_BACK, 0);
8205 processSync(mapper);
8206 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008207 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008208 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008209
8210 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008211 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008212 ASSERT_EQ(0, motionArgs.buttonState);
8213
Michael Wrightd02c5b62014-02-10 15:10:22 -08008214 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8215 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8216 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
8217
8218 // press BTN_SIDE, release BTN_SIDE
8219 processKey(mapper, BTN_SIDE, 1);
8220 processSync(mapper);
8221 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8222 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8223 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008224
Michael Wrightd02c5b62014-02-10 15:10:22 -08008225 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008226 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008227 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
8228
8229 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8230 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8231 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008232
8233 processKey(mapper, BTN_SIDE, 0);
8234 processSync(mapper);
8235 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008236 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008237 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008238
8239 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008240 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008241 ASSERT_EQ(0, motionArgs.buttonState);
8242
Michael Wrightd02c5b62014-02-10 15:10:22 -08008243 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8244 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8245 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
8246
8247 // press BTN_FORWARD, release BTN_FORWARD
8248 processKey(mapper, BTN_FORWARD, 1);
8249 processSync(mapper);
8250 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8251 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8252 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008253
Michael Wrightd02c5b62014-02-10 15:10:22 -08008254 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008255 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008256 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
8257
8258 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8259 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8260 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008261
8262 processKey(mapper, BTN_FORWARD, 0);
8263 processSync(mapper);
8264 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008265 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008266 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008267
8268 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008269 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008270 ASSERT_EQ(0, motionArgs.buttonState);
8271
Michael Wrightd02c5b62014-02-10 15:10:22 -08008272 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8273 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8274 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
8275
8276 // press BTN_EXTRA, release BTN_EXTRA
8277 processKey(mapper, BTN_EXTRA, 1);
8278 processSync(mapper);
8279 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8280 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8281 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008282
Michael Wrightd02c5b62014-02-10 15:10:22 -08008283 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008284 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008285 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
8286
8287 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8288 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8289 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008290
8291 processKey(mapper, BTN_EXTRA, 0);
8292 processSync(mapper);
8293 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008294 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008295 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008296
8297 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008298 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008299 ASSERT_EQ(0, motionArgs.buttonState);
8300
Michael Wrightd02c5b62014-02-10 15:10:22 -08008301 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8302 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8303 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
8304
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008305 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
8306
Michael Wrightd02c5b62014-02-10 15:10:22 -08008307 // press BTN_STYLUS, release BTN_STYLUS
8308 processKey(mapper, BTN_STYLUS, 1);
8309 processSync(mapper);
8310 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8311 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008312 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
8313
8314 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8315 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8316 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008317
8318 processKey(mapper, BTN_STYLUS, 0);
8319 processSync(mapper);
8320 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008321 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008322 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008323
8324 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008325 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008326 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008327
8328 // press BTN_STYLUS2, release BTN_STYLUS2
8329 processKey(mapper, BTN_STYLUS2, 1);
8330 processSync(mapper);
8331 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8332 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008333 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
8334
8335 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8336 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8337 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008338
8339 processKey(mapper, BTN_STYLUS2, 0);
8340 processSync(mapper);
8341 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008342 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008343 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008344
8345 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008346 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008347 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008348
8349 // release touch
8350 processId(mapper, -1);
8351 processSync(mapper);
8352 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8353 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8354 ASSERT_EQ(0, motionArgs.buttonState);
8355}
8356
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008357TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleMappedStylusButtons) {
8358 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008359 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008360 prepareAxes(POSITION | ID | SLOT);
Arpit Singha8c236b2023-04-25 13:56:05 +00008361 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008362
8363 mFakeEventHub->addKey(EVENTHUB_ID, BTN_A, 0, AKEYCODE_STYLUS_BUTTON_PRIMARY, 0);
8364 mFakeEventHub->addKey(EVENTHUB_ID, 0, 0xabcd, AKEYCODE_STYLUS_BUTTON_SECONDARY, 0);
8365
8366 // Touch down.
8367 processId(mapper, 1);
8368 processPosition(mapper, 100, 200);
8369 processSync(mapper);
8370 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8371 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithButtonState(0))));
8372
8373 // Press and release button mapped to the primary stylus button.
8374 processKey(mapper, BTN_A, 1);
8375 processSync(mapper);
8376 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8377 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
8378 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
8379 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8380 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
8381 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
8382
8383 processKey(mapper, BTN_A, 0);
8384 processSync(mapper);
8385 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8386 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithButtonState(0))));
8387 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8388 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
8389
8390 // Press and release the HID usage mapped to the secondary stylus button.
8391 processHidUsage(mapper, 0xabcd, 1);
8392 processSync(mapper);
8393 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8394 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
8395 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY))));
8396 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8397 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
8398 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY))));
8399
8400 processHidUsage(mapper, 0xabcd, 0);
8401 processSync(mapper);
8402 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8403 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithButtonState(0))));
8404 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8405 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
8406
8407 // Release touch.
8408 processId(mapper, -1);
8409 processSync(mapper);
8410 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8411 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
8412}
8413
Michael Wrightd02c5b62014-02-10 15:10:22 -08008414TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008415 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008416 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008417 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00008418 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008419
8420 NotifyMotionArgs motionArgs;
8421
8422 // default tool type is finger
8423 processId(mapper, 1);
8424 processPosition(mapper, 100, 200);
8425 processSync(mapper);
8426 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8427 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008428 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008429
8430 // eraser
8431 processKey(mapper, BTN_TOOL_RUBBER, 1);
8432 processSync(mapper);
8433 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8434 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008435 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008436
8437 // stylus
8438 processKey(mapper, BTN_TOOL_RUBBER, 0);
8439 processKey(mapper, BTN_TOOL_PEN, 1);
8440 processSync(mapper);
8441 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8442 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008443 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008444
8445 // brush
8446 processKey(mapper, BTN_TOOL_PEN, 0);
8447 processKey(mapper, BTN_TOOL_BRUSH, 1);
8448 processSync(mapper);
8449 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8450 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008451 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008452
8453 // pencil
8454 processKey(mapper, BTN_TOOL_BRUSH, 0);
8455 processKey(mapper, BTN_TOOL_PENCIL, 1);
8456 processSync(mapper);
8457 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8458 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008459 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008460
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08008461 // air-brush
Michael Wrightd02c5b62014-02-10 15:10:22 -08008462 processKey(mapper, BTN_TOOL_PENCIL, 0);
8463 processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
8464 processSync(mapper);
8465 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8466 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008467 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008468
8469 // mouse
8470 processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
8471 processKey(mapper, BTN_TOOL_MOUSE, 1);
8472 processSync(mapper);
8473 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8474 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008475 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008476
8477 // lens
8478 processKey(mapper, BTN_TOOL_MOUSE, 0);
8479 processKey(mapper, BTN_TOOL_LENS, 1);
8480 processSync(mapper);
8481 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8482 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008483 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008484
8485 // double-tap
8486 processKey(mapper, BTN_TOOL_LENS, 0);
8487 processKey(mapper, BTN_TOOL_DOUBLETAP, 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::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008492
8493 // triple-tap
8494 processKey(mapper, BTN_TOOL_DOUBLETAP, 0);
8495 processKey(mapper, BTN_TOOL_TRIPLETAP, 1);
8496 processSync(mapper);
8497 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8498 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008499 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008500
8501 // quad-tap
8502 processKey(mapper, BTN_TOOL_TRIPLETAP, 0);
8503 processKey(mapper, BTN_TOOL_QUADTAP, 1);
8504 processSync(mapper);
8505 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8506 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008507 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008508
8509 // finger
8510 processKey(mapper, BTN_TOOL_QUADTAP, 0);
8511 processKey(mapper, BTN_TOOL_FINGER, 1);
8512 processSync(mapper);
8513 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8514 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008515 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008516
8517 // stylus trumps finger
8518 processKey(mapper, BTN_TOOL_PEN, 1);
8519 processSync(mapper);
8520 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8521 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008522 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008523
8524 // eraser trumps stylus
8525 processKey(mapper, BTN_TOOL_RUBBER, 1);
8526 processSync(mapper);
8527 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8528 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008529 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008530
8531 // mouse trumps eraser
8532 processKey(mapper, BTN_TOOL_MOUSE, 1);
8533 processSync(mapper);
8534 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8535 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008536 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008537
8538 // MT tool type trumps BTN tool types: MT_TOOL_FINGER
8539 processToolType(mapper, MT_TOOL_FINGER); // this is the first time we send MT_TOOL_TYPE
8540 processSync(mapper);
8541 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8542 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008543 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008544
8545 // MT tool type trumps BTN tool types: MT_TOOL_PEN
8546 processToolType(mapper, MT_TOOL_PEN);
8547 processSync(mapper);
8548 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8549 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008550 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008551
8552 // back to default tool type
8553 processToolType(mapper, -1); // use a deliberately undefined tool type, for testing
8554 processKey(mapper, BTN_TOOL_MOUSE, 0);
8555 processKey(mapper, BTN_TOOL_RUBBER, 0);
8556 processKey(mapper, BTN_TOOL_PEN, 0);
8557 processKey(mapper, BTN_TOOL_FINGER, 0);
8558 processSync(mapper);
8559 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8560 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008561 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008562}
8563
8564TEST_F(MultiTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008565 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008566 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008567 prepareAxes(POSITION | ID | SLOT);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008568 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00008569 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008570
8571 NotifyMotionArgs motionArgs;
8572
8573 // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0
8574 processId(mapper, 1);
8575 processPosition(mapper, 100, 200);
8576 processSync(mapper);
8577 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8578 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8579 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8580 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8581
8582 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8583 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8584 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8585 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8586
8587 // move a little
8588 processPosition(mapper, 150, 250);
8589 processSync(mapper);
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 // down when BTN_TOUCH is pressed, pressure defaults to 1
8596 processKey(mapper, BTN_TOUCH, 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 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8604 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8605 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8606 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8607
8608 // up when BTN_TOUCH is released, hover restored
8609 processKey(mapper, BTN_TOUCH, 0);
8610 processSync(mapper);
8611 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8612 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8613 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8614 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8615
8616 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8617 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8618 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8619 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8620
8621 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8622 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8623 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8624 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8625
8626 // exit hover when pointer goes away
8627 processId(mapper, -1);
8628 processSync(mapper);
8629 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8630 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8631 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8632 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8633}
8634
8635TEST_F(MultiTouchInputMapperTest, Process_WhenAbsMTPressureIsPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008636 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008637 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008638 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00008639 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008640
8641 NotifyMotionArgs motionArgs;
8642
8643 // initially hovering because pressure is 0
8644 processId(mapper, 1);
8645 processPosition(mapper, 100, 200);
8646 processPressure(mapper, 0);
8647 processSync(mapper);
8648 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8649 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8650 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8651 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8652
8653 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8654 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8655 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8656 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8657
8658 // move a little
8659 processPosition(mapper, 150, 250);
8660 processSync(mapper);
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 // down when pressure becomes non-zero
8667 processPressure(mapper, RAW_PRESSURE_MAX);
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 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8675 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8676 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8677 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8678
8679 // up when pressure becomes 0, hover restored
8680 processPressure(mapper, 0);
8681 processSync(mapper);
8682 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8683 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8684 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8685 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8686
8687 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8688 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8689 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8690 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8691
8692 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8693 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8694 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8695 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8696
8697 // exit hover when pointer goes away
8698 processId(mapper, -1);
8699 processSync(mapper);
8700 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8701 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8702 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8703 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8704}
8705
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008706/**
8707 * Set the input device port <--> display port associations, and check that the
8708 * events are routed to the display that matches the display port.
8709 * This can be checked by looking at the displayId of the resulting NotifyMotionArgs.
8710 */
8711TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayPort) {
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008712 const std::string usb2 = "USB2";
8713 const uint8_t hdmi1 = 0;
8714 const uint8_t hdmi2 = 1;
8715 const std::string secondaryUniqueId = "uniqueId2";
Michael Wrightfe3de7d2020-07-02 19:05:30 +01008716 constexpr ViewportType type = ViewportType::EXTERNAL;
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008717
8718 addConfigurationProperty("touch.deviceType", "touchScreen");
8719 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008720 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008721
8722 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
8723 mFakePolicy->addInputPortAssociation(usb2, hdmi2);
8724
8725 // We are intentionally not adding the viewport for display 1 yet. Since the port association
8726 // for this input device is specified, and the matching viewport is not present,
8727 // the input device should be disabled (at the mapper level).
8728
8729 // Add viewport for display 2 on hdmi2
8730 prepareSecondaryDisplay(type, hdmi2);
8731 // Send a touch event
8732 processPosition(mapper, 100, 100);
8733 processSync(mapper);
8734 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
8735
8736 // Add viewport for display 1 on hdmi1
Michael Wrighta9cf4192022-12-01 23:46:39 +00008737 prepareDisplay(ui::ROTATION_0, hdmi1);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008738 // Send a touch event again
8739 processPosition(mapper, 100, 100);
8740 processSync(mapper);
8741
8742 NotifyMotionArgs args;
8743 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8744 ASSERT_EQ(DISPLAY_ID, args.displayId);
8745}
Michael Wrightd02c5b62014-02-10 15:10:22 -08008746
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008747TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayUniqueId) {
8748 addConfigurationProperty("touch.deviceType", "touchScreen");
8749 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008750 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008751
8752 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID);
8753
Michael Wrighta9cf4192022-12-01 23:46:39 +00008754 prepareDisplay(ui::ROTATION_0);
8755 prepareVirtualDisplay(ui::ROTATION_0);
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008756
8757 // Send a touch event
8758 processPosition(mapper, 100, 100);
8759 processSync(mapper);
8760
8761 NotifyMotionArgs args;
8762 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8763 ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId);
8764}
8765
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008766TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
Garfield Tan888a6a42020-01-09 11:39:16 -08008767 // Setup for second display.
Michael Wright17db18e2020-06-26 20:51:44 +01008768 std::shared_ptr<FakePointerController> fakePointerController =
8769 std::make_shared<FakePointerController>();
Garfield Tan888a6a42020-01-09 11:39:16 -08008770 fakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008771 fakePointerController->setPosition(100, 200);
Prabir Pradhan2853b7a2021-08-23 14:08:51 +00008772 mFakePolicy->setPointerController(fakePointerController);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008773
Garfield Tan888a6a42020-01-09 11:39:16 -08008774 mFakePolicy->setDefaultPointerDisplayId(SECONDARY_DISPLAY_ID);
Michael Wrightfe3de7d2020-07-02 19:05:30 +01008775 prepareSecondaryDisplay(ViewportType::EXTERNAL);
Garfield Tan888a6a42020-01-09 11:39:16 -08008776
Michael Wrighta9cf4192022-12-01 23:46:39 +00008777 prepareDisplay(ui::ROTATION_0);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008778 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008779 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008780
Josep del Río2d8c79a2023-01-23 19:33:50 +00008781 // Check source is mouse that would obtain the PointerController.
8782 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008783
8784 NotifyMotionArgs motionArgs;
8785 processPosition(mapper, 100, 100);
8786 processSync(mapper);
8787
8788 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8789 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8790 ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
8791}
8792
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008793/**
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008794 * Ensure that the readTime is set to the SYN_REPORT value when processing touch events.
8795 */
8796TEST_F(MultiTouchInputMapperTest, Process_SendsReadTime) {
8797 addConfigurationProperty("touch.deviceType", "touchScreen");
8798 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008799 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008800
Michael Wrighta9cf4192022-12-01 23:46:39 +00008801 prepareDisplay(ui::ROTATION_0);
Harry Cutts33476232023-01-30 19:57:29 +00008802 process(mapper, 10, /*readTime=*/11, EV_ABS, ABS_MT_TRACKING_ID, 1);
8803 process(mapper, 15, /*readTime=*/16, EV_ABS, ABS_MT_POSITION_X, 100);
8804 process(mapper, 20, /*readTime=*/21, EV_ABS, ABS_MT_POSITION_Y, 100);
8805 process(mapper, 25, /*readTime=*/26, EV_SYN, SYN_REPORT, 0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008806
8807 NotifyMotionArgs args;
8808 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8809 ASSERT_EQ(26, args.readTime);
8810
Harry Cutts33476232023-01-30 19:57:29 +00008811 process(mapper, 30, /*readTime=*/31, EV_ABS, ABS_MT_POSITION_X, 110);
8812 process(mapper, 30, /*readTime=*/32, EV_ABS, ABS_MT_POSITION_Y, 220);
8813 process(mapper, 30, /*readTime=*/33, EV_SYN, SYN_REPORT, 0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008814
8815 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8816 ASSERT_EQ(33, args.readTime);
8817}
8818
8819/**
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008820 * When the viewport is not active (isActive=false), the touch mapper should be disabled and the
8821 * events should not be delivered to the listener.
8822 */
8823TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreDropped) {
8824 addConfigurationProperty("touch.deviceType", "touchScreen");
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008825 // Don't set touch.enableForInactiveViewport to verify the default behavior.
Michael Wrighta9cf4192022-12-01 23:46:39 +00008826 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008827 /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008828 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008829 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008830 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008831
8832 NotifyMotionArgs motionArgs;
8833 processPosition(mapper, 100, 100);
8834 processSync(mapper);
8835
8836 mFakeListener->assertNotifyMotionWasNotCalled();
8837}
8838
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008839/**
8840 * When the viewport is not active (isActive=false) and touch.enableForInactiveViewport is true,
8841 * the touch mapper can process the events and the events can be delivered to the listener.
8842 */
8843TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreProcessed) {
8844 addConfigurationProperty("touch.deviceType", "touchScreen");
8845 addConfigurationProperty("touch.enableForInactiveViewport", "1");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008846 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008847 /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008848 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008849 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008850 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008851
8852 NotifyMotionArgs motionArgs;
8853 processPosition(mapper, 100, 100);
8854 processSync(mapper);
8855
8856 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8857 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8858}
8859
Josh Thielene986aed2023-06-01 14:17:30 +00008860/**
8861 * When the viewport is deactivated (isActive transitions from true to false),
8862 * and touch.enableForInactiveViewport is false, touches prior to the transition
8863 * should be cancelled.
8864 */
Garfield Tanc734e4f2021-01-15 20:01:39 -08008865TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_AbortTouches) {
8866 addConfigurationProperty("touch.deviceType", "touchScreen");
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008867 addConfigurationProperty("touch.enableForInactiveViewport", "0");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008868 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008869 /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008870 std::optional<DisplayViewport> optionalDisplayViewport =
8871 mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
8872 ASSERT_TRUE(optionalDisplayViewport.has_value());
8873 DisplayViewport displayViewport = *optionalDisplayViewport;
8874
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008875 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008876 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008877 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Garfield Tanc734e4f2021-01-15 20:01:39 -08008878
8879 // Finger down
8880 int32_t x = 100, y = 100;
8881 processPosition(mapper, x, y);
8882 processSync(mapper);
8883
8884 NotifyMotionArgs motionArgs;
8885 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8886 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8887
8888 // Deactivate display viewport
8889 displayViewport.isActive = false;
8890 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008891 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008892
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008893 // The ongoing touch should be canceled immediately
8894 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8895 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
8896
8897 // Finger move is ignored
Garfield Tanc734e4f2021-01-15 20:01:39 -08008898 x += 10, y += 10;
8899 processPosition(mapper, x, y);
8900 processSync(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008901 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
Garfield Tanc734e4f2021-01-15 20:01:39 -08008902
8903 // Reactivate display viewport
8904 displayViewport.isActive = true;
8905 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008906 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008907
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008908 // Finger move again starts new gesture
Garfield Tanc734e4f2021-01-15 20:01:39 -08008909 x += 10, y += 10;
8910 processPosition(mapper, x, y);
8911 processSync(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008912 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8913 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008914}
8915
Josh Thielene986aed2023-06-01 14:17:30 +00008916/**
8917 * When the viewport is deactivated (isActive transitions from true to false),
8918 * and touch.enableForInactiveViewport is true, touches prior to the transition
8919 * should not be cancelled.
8920 */
8921TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_TouchesNotAborted) {
8922 addConfigurationProperty("touch.deviceType", "touchScreen");
8923 addConfigurationProperty("touch.enableForInactiveViewport", "1");
8924 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
8925 /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
8926 std::optional<DisplayViewport> optionalDisplayViewport =
8927 mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
8928 ASSERT_TRUE(optionalDisplayViewport.has_value());
8929 DisplayViewport displayViewport = *optionalDisplayViewport;
8930
8931 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8932 prepareAxes(POSITION);
8933 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
8934
8935 // Finger down
8936 int32_t x = 100, y = 100;
8937 processPosition(mapper, x, y);
8938 processSync(mapper);
8939 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8940 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
8941
8942 // Deactivate display viewport
8943 displayViewport.isActive = false;
8944 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
8945 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8946
8947 // The ongoing touch should not be canceled
8948 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
8949
8950 // Finger move is not ignored
8951 x += 10, y += 10;
8952 processPosition(mapper, x, y);
8953 processSync(mapper);
8954 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8955 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
8956
8957 // Reactivate display viewport
8958 displayViewport.isActive = true;
8959 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
8960 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8961
8962 // Finger move continues and does not start new gesture
8963 x += 10, y += 10;
8964 processPosition(mapper, x, y);
8965 processSync(mapper);
8966 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8967 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
8968}
8969
Arthur Hung7c645402019-01-25 17:45:42 +08008970TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShowTouches) {
8971 // Setup the first touch screen device.
Arthur Hung7c645402019-01-25 17:45:42 +08008972 prepareAxes(POSITION | ID | SLOT);
8973 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00008974 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung7c645402019-01-25 17:45:42 +08008975
8976 // Create the second touch screen device, and enable multi fingers.
8977 const std::string USB2 = "USB2";
arthurhungdcef2dc2020-08-11 14:47:50 +08008978 const std::string DEVICE_NAME2 = "TOUCHSCREEN2";
Arthur Hung2c9a3342019-07-23 14:18:59 +08008979 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008980 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
arthurhungdcef2dc2020-08-11 14:47:50 +08008981 std::shared_ptr<InputDevice> device2 =
8982 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
Dominik Laskowski2f01d772022-03-23 16:01:29 -07008983 ftl::Flags<InputDeviceClass>(0));
arthurhungdcef2dc2020-08-11 14:47:50 +08008984
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008985 mFakeEventHub->addAbsoluteAxis(SECOND_EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX,
Harry Cutts33476232023-01-30 19:57:29 +00008986 /*flat=*/0, /*fuzz=*/0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008987 mFakeEventHub->addAbsoluteAxis(SECOND_EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX,
Harry Cutts33476232023-01-30 19:57:29 +00008988 /*flat=*/0, /*fuzz=*/0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008989 mFakeEventHub->addAbsoluteAxis(SECOND_EVENTHUB_ID, ABS_MT_TRACKING_ID, RAW_ID_MIN, RAW_ID_MAX,
Harry Cutts33476232023-01-30 19:57:29 +00008990 /*flat=*/0, /*fuzz=*/0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008991 mFakeEventHub->addAbsoluteAxis(SECOND_EVENTHUB_ID, ABS_MT_SLOT, RAW_SLOT_MIN, RAW_SLOT_MAX,
Harry Cutts33476232023-01-30 19:57:29 +00008992 /*flat=*/0, /*fuzz=*/0);
8993 mFakeEventHub->setAbsoluteAxisValue(SECOND_EVENTHUB_ID, ABS_MT_SLOT, /*value=*/0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008994 mFakeEventHub->addConfigurationProperty(SECOND_EVENTHUB_ID, String8("touch.deviceType"),
8995 String8("touchScreen"));
Arthur Hung7c645402019-01-25 17:45:42 +08008996
8997 // Setup the second touch screen device.
Arpit Singha8c236b2023-04-25 13:56:05 +00008998 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
8999 MultiTouchInputMapper& mapper2 = device2->constructAndAddMapper<
9000 MultiTouchInputMapper>(SECOND_EVENTHUB_ID, mFakePolicy->getReaderConfiguration());
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07009001 std::list<NotifyArgs> unused =
9002 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00009003 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07009004 unused += device2->reset(ARBITRARY_TIME);
Arthur Hung7c645402019-01-25 17:45:42 +08009005
9006 // Setup PointerController.
Michael Wright17db18e2020-06-26 20:51:44 +01009007 std::shared_ptr<FakePointerController> fakePointerController =
9008 std::make_shared<FakePointerController>();
Prabir Pradhan2853b7a2021-08-23 14:08:51 +00009009 mFakePolicy->setPointerController(fakePointerController);
Arthur Hung7c645402019-01-25 17:45:42 +08009010
9011 // Setup policy for associated displays and show touches.
9012 const uint8_t hdmi1 = 0;
9013 const uint8_t hdmi2 = 1;
9014 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
9015 mFakePolicy->addInputPortAssociation(USB2, hdmi2);
9016 mFakePolicy->setShowTouches(true);
9017
9018 // Create displays.
Michael Wrighta9cf4192022-12-01 23:46:39 +00009019 prepareDisplay(ui::ROTATION_0, hdmi1);
Michael Wrightfe3de7d2020-07-02 19:05:30 +01009020 prepareSecondaryDisplay(ViewportType::EXTERNAL, hdmi2);
Arthur Hung7c645402019-01-25 17:45:42 +08009021
9022 // Default device will reconfigure above, need additional reconfiguration for another device.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07009023 unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00009024 InputReaderConfiguration::Change::DISPLAY_INFO |
9025 InputReaderConfiguration::Change::SHOW_TOUCHES);
Arthur Hung7c645402019-01-25 17:45:42 +08009026
9027 // Two fingers down at default display.
9028 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
9029 processPosition(mapper, x1, y1);
9030 processId(mapper, 1);
9031 processSlot(mapper, 1);
9032 processPosition(mapper, x2, y2);
9033 processId(mapper, 2);
9034 processSync(mapper);
9035
9036 std::map<int32_t, std::vector<int32_t>>::const_iterator iter =
9037 fakePointerController->getSpots().find(DISPLAY_ID);
9038 ASSERT_TRUE(iter != fakePointerController->getSpots().end());
9039 ASSERT_EQ(size_t(2), iter->second.size());
9040
9041 // Two fingers down at second display.
9042 processPosition(mapper2, x1, y1);
9043 processId(mapper2, 1);
9044 processSlot(mapper2, 1);
9045 processPosition(mapper2, x2, y2);
9046 processId(mapper2, 2);
9047 processSync(mapper2);
9048
9049 iter = fakePointerController->getSpots().find(SECONDARY_DISPLAY_ID);
9050 ASSERT_TRUE(iter != fakePointerController->getSpots().end());
9051 ASSERT_EQ(size_t(2), iter->second.size());
Prabir Pradhan197e0862022-07-01 14:28:00 +00009052
9053 // Disable the show touches configuration and ensure the spots are cleared.
9054 mFakePolicy->setShowTouches(false);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07009055 unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00009056 InputReaderConfiguration::Change::SHOW_TOUCHES);
Prabir Pradhan197e0862022-07-01 14:28:00 +00009057
9058 ASSERT_TRUE(fakePointerController->getSpots().empty());
Arthur Hung7c645402019-01-25 17:45:42 +08009059}
9060
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06009061TEST_F(MultiTouchInputMapperTest, VideoFrames_ReceivedByListener) {
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06009062 prepareAxes(POSITION);
9063 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009064 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00009065 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06009066
9067 NotifyMotionArgs motionArgs;
9068 // Unrotated video frame
9069 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
9070 std::vector<TouchVideoFrame> frames{frame};
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009071 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06009072 processPosition(mapper, 100, 200);
9073 processSync(mapper);
9074 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9075 ASSERT_EQ(frames, motionArgs.videoFrames);
9076
9077 // Subsequent touch events should not have any videoframes
9078 // This is implemented separately in FakeEventHub,
9079 // but that should match the behaviour of TouchVideoDevice.
9080 processPosition(mapper, 200, 200);
9081 processSync(mapper);
9082 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9083 ASSERT_EQ(std::vector<TouchVideoFrame>(), motionArgs.videoFrames);
9084}
9085
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009086TEST_F(MultiTouchInputMapperTest, VideoFrames_AreNotRotated) {
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009087 prepareAxes(POSITION);
9088 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00009089 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009090 // Unrotated video frame
9091 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
9092 NotifyMotionArgs motionArgs;
9093
9094 // Test all 4 orientations
Michael Wrighta9cf4192022-12-01 23:46:39 +00009095 for (ui::Rotation orientation : ftl::enum_range<ui::Rotation>()) {
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009096 SCOPED_TRACE("Orientation " + StringPrintf("%i", orientation));
9097 clearViewports();
9098 prepareDisplay(orientation);
9099 std::vector<TouchVideoFrame> frames{frame};
9100 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
9101 processPosition(mapper, 100, 200);
9102 processSync(mapper);
9103 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9104 ASSERT_EQ(frames, motionArgs.videoFrames);
9105 }
9106}
9107
9108TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_AreRotated) {
9109 prepareAxes(POSITION);
9110 addConfigurationProperty("touch.deviceType", "touchScreen");
9111 // Since InputReader works in the un-rotated coordinate space, only devices that are not
9112 // orientation-aware are affected by display rotation.
9113 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00009114 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009115 // Unrotated video frame
9116 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
9117 NotifyMotionArgs motionArgs;
9118
9119 // Test all 4 orientations
Michael Wrighta9cf4192022-12-01 23:46:39 +00009120 for (ui::Rotation orientation : ftl::enum_range<ui::Rotation>()) {
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009121 SCOPED_TRACE("Orientation " + StringPrintf("%i", orientation));
9122 clearViewports();
9123 prepareDisplay(orientation);
9124 std::vector<TouchVideoFrame> frames{frame};
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009125 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009126 processPosition(mapper, 100, 200);
9127 processSync(mapper);
9128 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009129 // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction
9130 // compared to the display. This is so that when the window transform (which contains the
9131 // display rotation) is applied later by InputDispatcher, the coordinates end up in the
9132 // window's coordinate space.
9133 frames[0].rotate(getInverseRotation(orientation));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009134 ASSERT_EQ(frames, motionArgs.videoFrames);
lilinnan687e58f2022-07-19 16:00:50 +08009135
9136 // Release finger.
9137 processSync(mapper);
9138 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009139 }
9140}
9141
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009142TEST_F(MultiTouchInputMapperTest, VideoFrames_MultipleFramesAreNotRotated) {
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009143 prepareAxes(POSITION);
9144 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00009145 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009146 // Unrotated video frames. There's no rule that they must all have the same dimensions,
9147 // so mix these.
9148 TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
9149 TouchVideoFrame frame2(3, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {1, 3});
9150 TouchVideoFrame frame3(2, 2, {10, 20, 10, 0}, {1, 4});
9151 std::vector<TouchVideoFrame> frames{frame1, frame2, frame3};
9152 NotifyMotionArgs motionArgs;
9153
Michael Wrighta9cf4192022-12-01 23:46:39 +00009154 prepareDisplay(ui::ROTATION_90);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009155 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009156 processPosition(mapper, 100, 200);
9157 processSync(mapper);
9158 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009159 ASSERT_EQ(frames, motionArgs.videoFrames);
9160}
9161
9162TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_MultipleFramesAreRotated) {
9163 prepareAxes(POSITION);
9164 addConfigurationProperty("touch.deviceType", "touchScreen");
9165 // Since InputReader works in the un-rotated coordinate space, only devices that are not
9166 // orientation-aware are affected by display rotation.
9167 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00009168 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009169 // Unrotated video frames. There's no rule that they must all have the same dimensions,
9170 // so mix these.
9171 TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
9172 TouchVideoFrame frame2(3, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {1, 3});
9173 TouchVideoFrame frame3(2, 2, {10, 20, 10, 0}, {1, 4});
9174 std::vector<TouchVideoFrame> frames{frame1, frame2, frame3};
9175 NotifyMotionArgs motionArgs;
9176
Michael Wrighta9cf4192022-12-01 23:46:39 +00009177 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009178 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
9179 processPosition(mapper, 100, 200);
9180 processSync(mapper);
9181 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9182 std::for_each(frames.begin(), frames.end(), [](TouchVideoFrame& frame) {
9183 // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction
9184 // compared to the display. This is so that when the window transform (which contains the
9185 // display rotation) is applied later by InputDispatcher, the coordinates end up in the
9186 // window's coordinate space.
Michael Wrighta9cf4192022-12-01 23:46:39 +00009187 frame.rotate(getInverseRotation(ui::ROTATION_90));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009188 });
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009189 ASSERT_EQ(frames, motionArgs.videoFrames);
9190}
9191
Arthur Hung9da14732019-09-02 16:16:58 +08009192/**
9193 * If we had defined port associations, but the viewport is not ready, the touch device would be
9194 * expected to be disabled, and it should be enabled after the viewport has found.
9195 */
9196TEST_F(MultiTouchInputMapperTest, Configure_EnabledForAssociatedDisplay) {
Arthur Hung9da14732019-09-02 16:16:58 +08009197 constexpr uint8_t hdmi2 = 1;
9198 const std::string secondaryUniqueId = "uniqueId2";
Michael Wrightfe3de7d2020-07-02 19:05:30 +01009199 constexpr ViewportType type = ViewportType::EXTERNAL;
Arthur Hung9da14732019-09-02 16:16:58 +08009200
9201 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi2);
9202
9203 addConfigurationProperty("touch.deviceType", "touchScreen");
9204 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00009205 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung9da14732019-09-02 16:16:58 +08009206
9207 ASSERT_EQ(mDevice->isEnabled(), false);
9208
9209 // Add display on hdmi2, the device should be enabled and can receive touch event.
9210 prepareSecondaryDisplay(type, hdmi2);
9211 ASSERT_EQ(mDevice->isEnabled(), true);
9212
9213 // Send a touch event.
9214 processPosition(mapper, 100, 100);
9215 processSync(mapper);
9216
9217 NotifyMotionArgs args;
9218 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9219 ASSERT_EQ(SECONDARY_DISPLAY_ID, args.displayId);
9220}
9221
Arthur Hung421eb1c2020-01-16 00:09:42 +08009222TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleSingleTouch) {
Arthur Hung421eb1c2020-01-16 00:09:42 +08009223 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009224 prepareDisplay(ui::ROTATION_0);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009225 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009226 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung421eb1c2020-01-16 00:09:42 +08009227
9228 NotifyMotionArgs motionArgs;
9229
9230 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
9231 // finger down
9232 processId(mapper, 1);
9233 processPosition(mapper, x1, y1);
9234 processSync(mapper);
9235 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9236 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009237 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009238
9239 // finger move
9240 processId(mapper, 1);
9241 processPosition(mapper, x2, y2);
9242 processSync(mapper);
9243 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9244 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009245 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009246
9247 // finger up.
9248 processId(mapper, -1);
9249 processSync(mapper);
9250 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9251 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009252 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009253
9254 // new finger down
9255 processId(mapper, 1);
9256 processPosition(mapper, x3, y3);
9257 processSync(mapper);
9258 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9259 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009260 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009261}
9262
9263/**
arthurhungcc7f9802020-04-30 17:55:40 +08009264 * Test single touch should be canceled when received the MT_TOOL_PALM event, and the following
9265 * MOVE and UP events should be ignored.
Arthur Hung421eb1c2020-01-16 00:09:42 +08009266 */
arthurhungcc7f9802020-04-30 17:55:40 +08009267TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_SinglePointer) {
Arthur Hung421eb1c2020-01-16 00:09:42 +08009268 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009269 prepareDisplay(ui::ROTATION_0);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009270 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009271 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung421eb1c2020-01-16 00:09:42 +08009272
9273 NotifyMotionArgs motionArgs;
9274
9275 // default tool type is finger
9276 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
arthurhungcc7f9802020-04-30 17:55:40 +08009277 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009278 processPosition(mapper, x1, y1);
9279 processSync(mapper);
9280 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9281 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009282 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009283
9284 // Tool changed to MT_TOOL_PALM expect sending the cancel event.
9285 processToolType(mapper, MT_TOOL_PALM);
9286 processSync(mapper);
9287 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9288 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9289
9290 // Ignore the following MOVE and UP events if had detect a palm event.
arthurhungcc7f9802020-04-30 17:55:40 +08009291 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009292 processPosition(mapper, x2, y2);
9293 processSync(mapper);
9294 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9295
9296 // finger up.
arthurhungcc7f9802020-04-30 17:55:40 +08009297 processId(mapper, INVALID_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009298 processSync(mapper);
9299 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9300
9301 // new finger down
arthurhungcc7f9802020-04-30 17:55:40 +08009302 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009303 processToolType(mapper, MT_TOOL_FINGER);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009304 processPosition(mapper, x3, y3);
9305 processSync(mapper);
9306 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9307 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009308 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009309}
9310
arthurhungbf89a482020-04-17 17:37:55 +08009311/**
arthurhungcc7f9802020-04-30 17:55:40 +08009312 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event from some finger,
9313 * and the rest active fingers could still be allowed to receive the events
arthurhungbf89a482020-04-17 17:37:55 +08009314 */
arthurhungcc7f9802020-04-30 17:55:40 +08009315TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_TwoPointers) {
arthurhungbf89a482020-04-17 17:37:55 +08009316 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009317 prepareDisplay(ui::ROTATION_0);
arthurhungbf89a482020-04-17 17:37:55 +08009318 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009319 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungbf89a482020-04-17 17:37:55 +08009320
9321 NotifyMotionArgs motionArgs;
9322
9323 // default tool type is finger
arthurhungcc7f9802020-04-30 17:55:40 +08009324 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220;
9325 processId(mapper, FIRST_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009326 processPosition(mapper, x1, y1);
9327 processSync(mapper);
9328 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9329 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009330 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungbf89a482020-04-17 17:37:55 +08009331
9332 // Second finger down.
arthurhungcc7f9802020-04-30 17:55:40 +08009333 processSlot(mapper, SECOND_SLOT);
9334 processId(mapper, SECOND_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009335 processPosition(mapper, x2, y2);
arthurhungcc7f9802020-04-30 17:55:40 +08009336 processSync(mapper);
9337 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009338 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009339 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009340
9341 // If the tool type of the first finger changes to MT_TOOL_PALM,
9342 // we expect to receive ACTION_POINTER_UP with cancel flag.
9343 processSlot(mapper, FIRST_SLOT);
9344 processId(mapper, FIRST_TRACKING_ID);
9345 processToolType(mapper, MT_TOOL_PALM);
9346 processSync(mapper);
9347 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009348 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009349 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9350
9351 // The following MOVE events of second finger should be processed.
9352 processSlot(mapper, SECOND_SLOT);
9353 processId(mapper, SECOND_TRACKING_ID);
9354 processPosition(mapper, x2 + 1, y2 + 1);
9355 processSync(mapper);
9356 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9357 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009358 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009359
9360 // First finger up. It used to be in palm mode, and we already generated ACTION_POINTER_UP for
9361 // it. Second finger receive move.
9362 processSlot(mapper, FIRST_SLOT);
9363 processId(mapper, INVALID_TRACKING_ID);
9364 processSync(mapper);
9365 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9366 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009367 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009368
9369 // Second finger keeps moving.
9370 processSlot(mapper, SECOND_SLOT);
9371 processId(mapper, SECOND_TRACKING_ID);
9372 processPosition(mapper, x2 + 2, y2 + 2);
9373 processSync(mapper);
9374 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9375 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009376 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009377
9378 // Second finger up.
9379 processId(mapper, INVALID_TRACKING_ID);
9380 processSync(mapper);
9381 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9382 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9383 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9384}
9385
9386/**
9387 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event, if only 1 finger
9388 * is active, it should send CANCEL after receiving the MT_TOOL_PALM event.
9389 */
9390TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_ShouldCancelWhenAllTouchIsPalm) {
9391 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009392 prepareDisplay(ui::ROTATION_0);
arthurhungcc7f9802020-04-30 17:55:40 +08009393 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009394 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungcc7f9802020-04-30 17:55:40 +08009395
9396 NotifyMotionArgs motionArgs;
9397
9398 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
9399 // First finger down.
9400 processId(mapper, FIRST_TRACKING_ID);
9401 processPosition(mapper, x1, y1);
9402 processSync(mapper);
9403 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9404 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009405 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009406
9407 // Second finger down.
9408 processSlot(mapper, SECOND_SLOT);
9409 processId(mapper, SECOND_TRACKING_ID);
9410 processPosition(mapper, x2, y2);
arthurhungbf89a482020-04-17 17:37:55 +08009411 processSync(mapper);
9412 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009413 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009414 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungbf89a482020-04-17 17:37:55 +08009415
arthurhungcc7f9802020-04-30 17:55:40 +08009416 // If the tool type of the first finger changes to MT_TOOL_PALM,
9417 // we expect to receive ACTION_POINTER_UP with cancel flag.
9418 processSlot(mapper, FIRST_SLOT);
9419 processId(mapper, FIRST_TRACKING_ID);
9420 processToolType(mapper, MT_TOOL_PALM);
9421 processSync(mapper);
9422 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009423 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009424 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9425
9426 // Second finger keeps moving.
9427 processSlot(mapper, SECOND_SLOT);
9428 processId(mapper, SECOND_TRACKING_ID);
9429 processPosition(mapper, x2 + 1, y2 + 1);
9430 processSync(mapper);
9431 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9432 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9433
9434 // second finger becomes palm, receive cancel due to only 1 finger is active.
9435 processId(mapper, SECOND_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009436 processToolType(mapper, MT_TOOL_PALM);
9437 processSync(mapper);
9438 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9439 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9440
arthurhungcc7f9802020-04-30 17:55:40 +08009441 // third finger down.
9442 processSlot(mapper, THIRD_SLOT);
9443 processId(mapper, THIRD_TRACKING_ID);
9444 processToolType(mapper, MT_TOOL_FINGER);
arthurhungbf89a482020-04-17 17:37:55 +08009445 processPosition(mapper, x3, y3);
9446 processSync(mapper);
arthurhungbf89a482020-04-17 17:37:55 +08009447 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9448 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009449 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009450 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009451
9452 // third finger move
9453 processId(mapper, THIRD_TRACKING_ID);
9454 processPosition(mapper, x3 + 1, y3 + 1);
9455 processSync(mapper);
9456 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9457 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9458
9459 // first finger up, third finger receive move.
9460 processSlot(mapper, FIRST_SLOT);
9461 processId(mapper, INVALID_TRACKING_ID);
9462 processSync(mapper);
9463 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9464 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009465 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009466
9467 // second finger up, third finger receive move.
9468 processSlot(mapper, SECOND_SLOT);
9469 processId(mapper, INVALID_TRACKING_ID);
9470 processSync(mapper);
9471 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9472 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009473 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009474
9475 // third finger up.
9476 processSlot(mapper, THIRD_SLOT);
9477 processId(mapper, INVALID_TRACKING_ID);
9478 processSync(mapper);
9479 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9480 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9481 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9482}
9483
9484/**
9485 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event from some finger,
9486 * and the active finger could still be allowed to receive the events
9487 */
9488TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_KeepFirstPointer) {
9489 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009490 prepareDisplay(ui::ROTATION_0);
arthurhungcc7f9802020-04-30 17:55:40 +08009491 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009492 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungcc7f9802020-04-30 17:55:40 +08009493
9494 NotifyMotionArgs motionArgs;
9495
9496 // default tool type is finger
9497 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220;
9498 processId(mapper, FIRST_TRACKING_ID);
9499 processPosition(mapper, x1, y1);
9500 processSync(mapper);
9501 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9502 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009503 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009504
9505 // Second finger down.
9506 processSlot(mapper, SECOND_SLOT);
9507 processId(mapper, SECOND_TRACKING_ID);
9508 processPosition(mapper, x2, y2);
9509 processSync(mapper);
9510 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009511 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009512 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009513
9514 // If the tool type of the second finger changes to MT_TOOL_PALM,
9515 // we expect to receive ACTION_POINTER_UP with cancel flag.
9516 processId(mapper, SECOND_TRACKING_ID);
9517 processToolType(mapper, MT_TOOL_PALM);
9518 processSync(mapper);
9519 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009520 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009521 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9522
9523 // The following MOVE event should be processed.
9524 processSlot(mapper, FIRST_SLOT);
9525 processId(mapper, FIRST_TRACKING_ID);
9526 processPosition(mapper, x1 + 1, y1 + 1);
9527 processSync(mapper);
9528 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9529 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009530 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009531
9532 // second finger up.
9533 processSlot(mapper, SECOND_SLOT);
9534 processId(mapper, INVALID_TRACKING_ID);
9535 processSync(mapper);
9536 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9537 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9538
9539 // first finger keep moving
9540 processSlot(mapper, FIRST_SLOT);
9541 processId(mapper, FIRST_TRACKING_ID);
9542 processPosition(mapper, x1 + 2, y1 + 2);
9543 processSync(mapper);
9544 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9545 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9546
9547 // first finger up.
9548 processId(mapper, INVALID_TRACKING_ID);
9549 processSync(mapper);
9550 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9551 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9552 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
arthurhungbf89a482020-04-17 17:37:55 +08009553}
9554
Arthur Hung9ad18942021-06-19 02:04:46 +00009555/**
9556 * Test multi-touch should sent ACTION_POINTER_UP/ACTION_UP when received the INVALID_TRACKING_ID,
9557 * to prevent the driver side may send unexpected data after set tracking id as INVALID_TRACKING_ID
9558 * cause slot be valid again.
9559 */
9560TEST_F(MultiTouchInputMapperTest, Process_MultiTouch_WithInvalidTrackingId) {
9561 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009562 prepareDisplay(ui::ROTATION_0);
Arthur Hung9ad18942021-06-19 02:04:46 +00009563 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009564 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung9ad18942021-06-19 02:04:46 +00009565
9566 NotifyMotionArgs motionArgs;
9567
9568 constexpr int32_t x1 = 100, y1 = 200, x2 = 0, y2 = 0;
9569 // First finger down.
9570 processId(mapper, FIRST_TRACKING_ID);
9571 processPosition(mapper, x1, y1);
9572 processPressure(mapper, RAW_PRESSURE_MAX);
9573 processSync(mapper);
9574 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9575 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009576 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009577
9578 // First finger move.
9579 processId(mapper, FIRST_TRACKING_ID);
9580 processPosition(mapper, x1 + 1, y1 + 1);
9581 processPressure(mapper, RAW_PRESSURE_MAX);
9582 processSync(mapper);
9583 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9584 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009585 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009586
9587 // Second finger down.
9588 processSlot(mapper, SECOND_SLOT);
9589 processId(mapper, SECOND_TRACKING_ID);
9590 processPosition(mapper, x2, y2);
9591 processPressure(mapper, RAW_PRESSURE_MAX);
9592 processSync(mapper);
9593 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009594 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009595 ASSERT_EQ(uint32_t(2), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009596
9597 // second finger up with some unexpected data.
9598 processSlot(mapper, SECOND_SLOT);
9599 processId(mapper, INVALID_TRACKING_ID);
9600 processPosition(mapper, x2, y2);
9601 processSync(mapper);
9602 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009603 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009604 ASSERT_EQ(uint32_t(2), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009605
9606 // first finger up with some unexpected data.
9607 processSlot(mapper, FIRST_SLOT);
9608 processId(mapper, INVALID_TRACKING_ID);
9609 processPosition(mapper, x2, y2);
9610 processPressure(mapper, RAW_PRESSURE_MAX);
9611 processSync(mapper);
9612 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9613 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009614 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009615}
9616
Arpit Singh4b4a4572023-11-24 18:19:56 +00009617TEST_F(MultiTouchInputMapperTest, Reset_RepopulatesMultiTouchState) {
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009618 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009619 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009620 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009621 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009622
9623 // First finger down.
Arpit Singh4b4a4572023-11-24 18:19:56 +00009624 constexpr int32_t x1 = 100, y1 = 200, x2 = 300, y2 = 400;
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009625 processId(mapper, FIRST_TRACKING_ID);
Arpit Singh4b4a4572023-11-24 18:19:56 +00009626 processPosition(mapper, x1, y1);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009627 processPressure(mapper, RAW_PRESSURE_MAX);
9628 processSync(mapper);
9629 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9630 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
9631
9632 // Second finger down.
9633 processSlot(mapper, SECOND_SLOT);
9634 processId(mapper, SECOND_TRACKING_ID);
Arpit Singh4b4a4572023-11-24 18:19:56 +00009635 processPosition(mapper, x2, y2);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009636 processPressure(mapper, RAW_PRESSURE_MAX);
9637 processSync(mapper);
9638 ASSERT_NO_FATAL_FAILURE(
9639 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(ACTION_POINTER_1_DOWN)));
9640
Arpit Singh4b4a4572023-11-24 18:19:56 +00009641 // Set MT Slot state to be repopulated for the required slots
9642 std::vector<int32_t> mtSlotValues(RAW_SLOT_MAX + 1, -1);
9643 mtSlotValues[0] = FIRST_TRACKING_ID;
9644 mtSlotValues[1] = SECOND_TRACKING_ID;
9645 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_TRACKING_ID, mtSlotValues);
9646
9647 mtSlotValues[0] = x1;
9648 mtSlotValues[1] = x2;
9649 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_POSITION_X, mtSlotValues);
9650
9651 mtSlotValues[0] = y1;
9652 mtSlotValues[1] = y2;
9653 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_POSITION_Y, mtSlotValues);
9654
9655 mtSlotValues[0] = RAW_PRESSURE_MAX;
9656 mtSlotValues[1] = RAW_PRESSURE_MAX;
9657 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_PRESSURE, mtSlotValues);
9658
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009659 // Reset the mapper. When the mapper is reset, we expect the current multi-touch state to be
Arpit Singh4b4a4572023-11-24 18:19:56 +00009660 // repopulated. Resetting should cancel the ongoing gesture.
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00009661 resetMapper(mapper, ARBITRARY_TIME);
9662 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9663 WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009664
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009665 // Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
9666 // the existing touch state to generate a down event.
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009667 processPosition(mapper, 301, 302);
9668 processSync(mapper);
9669 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9670 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPressure(1.f))));
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009671 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9672 AllOf(WithMotionAction(ACTION_POINTER_1_DOWN), WithPressure(1.f))));
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009673
9674 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9675}
9676
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009677TEST_F(MultiTouchInputMapperTest, Reset_PreservesLastTouchState_NoPointersDown) {
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009678 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009679 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009680 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009681 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009682
9683 // First finger touches down and releases.
9684 processId(mapper, FIRST_TRACKING_ID);
9685 processPosition(mapper, 100, 200);
9686 processPressure(mapper, RAW_PRESSURE_MAX);
9687 processSync(mapper);
9688 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9689 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
9690 processId(mapper, INVALID_TRACKING_ID);
9691 processSync(mapper);
9692 ASSERT_NO_FATAL_FAILURE(
9693 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
9694
9695 // Reset the mapper. When the mapper is reset, we expect it to restore the latest
9696 // raw state where no pointers are down.
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00009697 resetMapper(mapper, ARBITRARY_TIME);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009698 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9699
9700 // Send an empty sync frame. Since there are no pointers, no events are generated.
9701 processSync(mapper);
9702 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9703}
9704
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009705TEST_F(MultiTouchInputMapperTest, StylusSourceIsAddedDynamicallyFromToolType) {
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009706 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009707 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009708 prepareAxes(POSITION | ID | SLOT | PRESSURE | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009709 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009710 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009711
9712 // Even if the device supports reporting the ABS_MT_TOOL_TYPE axis, which could give it the
9713 // ability to report MT_TOOL_PEN, we do not report the device as coming from a stylus source.
9714 // Due to limitations in the evdev protocol, we cannot say for certain that a device is capable
9715 // of reporting stylus events just because it supports ABS_MT_TOOL_TYPE.
9716 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
9717
9718 // However, if the device ever ends up reporting an event with MT_TOOL_PEN, it should be
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009719 // reported with the stylus source.
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009720 processId(mapper, FIRST_TRACKING_ID);
9721 processToolType(mapper, MT_TOOL_PEN);
9722 processPosition(mapper, 100, 200);
9723 processPressure(mapper, RAW_PRESSURE_MAX);
9724 processSync(mapper);
9725 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9726 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
9727 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009728 WithToolType(ToolType::STYLUS))));
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009729
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009730 // Now that we know the device supports styluses, ensure that the device is re-configured with
9731 // the stylus source.
9732 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, mapper.getSources());
9733 {
9734 const auto& devices = mReader->getInputDevices();
9735 auto deviceInfo =
9736 std::find_if(devices.begin(), devices.end(),
9737 [](const InputDeviceInfo& info) { return info.getId() == DEVICE_ID; });
9738 LOG_ALWAYS_FATAL_IF(deviceInfo == devices.end(), "Cannot find InputDevice");
9739 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, deviceInfo->getSources());
9740 }
9741
9742 // Ensure the device was not reset to prevent interruptions of any ongoing gestures.
9743 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
9744
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009745 processId(mapper, INVALID_TRACKING_ID);
9746 processSync(mapper);
9747 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9748 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
9749 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009750 WithToolType(ToolType::STYLUS))));
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009751}
9752
Seunghwan Choi356026c2023-02-01 14:37:25 +09009753TEST_F(MultiTouchInputMapperTest, Process_WhenConfigEnabled_ShouldShowDirectStylusPointer) {
9754 addConfigurationProperty("touch.deviceType", "touchScreen");
9755 prepareDisplay(ui::ROTATION_0);
9756 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE | PRESSURE);
9757 // Add BTN_TOOL_PEN to statically show stylus support, since using ABS_MT_TOOL_TYPE can only
9758 // indicate stylus presence dynamically.
9759 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
9760 std::shared_ptr<FakePointerController> fakePointerController =
9761 std::make_shared<FakePointerController>();
9762 mFakePolicy->setPointerController(fakePointerController);
9763 mFakePolicy->setStylusPointerIconEnabled(true);
Arpit Singha8c236b2023-04-25 13:56:05 +00009764 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Seunghwan Choi356026c2023-02-01 14:37:25 +09009765
9766 processId(mapper, FIRST_TRACKING_ID);
9767 processPressure(mapper, RAW_PRESSURE_MIN);
9768 processPosition(mapper, 100, 200);
9769 processToolType(mapper, MT_TOOL_PEN);
9770 processSync(mapper);
9771 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9772 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009773 WithToolType(ToolType::STYLUS),
Seunghwan Choi356026c2023-02-01 14:37:25 +09009774 WithPointerCoords(0, toDisplayX(100), toDisplayY(200)))));
9775 ASSERT_TRUE(fakePointerController->isPointerShown());
9776 ASSERT_NO_FATAL_FAILURE(
9777 fakePointerController->assertPosition(toDisplayX(100), toDisplayY(200)));
9778}
9779
9780TEST_F(MultiTouchInputMapperTest, Process_WhenConfigDisabled_ShouldNotShowDirectStylusPointer) {
9781 addConfigurationProperty("touch.deviceType", "touchScreen");
9782 prepareDisplay(ui::ROTATION_0);
9783 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE | PRESSURE);
9784 // Add BTN_TOOL_PEN to statically show stylus support, since using ABS_MT_TOOL_TYPE can only
9785 // indicate stylus presence dynamically.
9786 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
9787 std::shared_ptr<FakePointerController> fakePointerController =
9788 std::make_shared<FakePointerController>();
9789 mFakePolicy->setPointerController(fakePointerController);
9790 mFakePolicy->setStylusPointerIconEnabled(false);
Arpit Singha8c236b2023-04-25 13:56:05 +00009791 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Seunghwan Choi356026c2023-02-01 14:37:25 +09009792
9793 processId(mapper, FIRST_TRACKING_ID);
9794 processPressure(mapper, RAW_PRESSURE_MIN);
9795 processPosition(mapper, 100, 200);
9796 processToolType(mapper, MT_TOOL_PEN);
9797 processSync(mapper);
9798 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9799 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009800 WithToolType(ToolType::STYLUS),
Seunghwan Choi356026c2023-02-01 14:37:25 +09009801 WithPointerCoords(0, toDisplayX(100), toDisplayY(200)))));
9802 ASSERT_FALSE(fakePointerController->isPointerShown());
9803}
9804
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009805// --- MultiTouchInputMapperTest_ExternalDevice ---
9806
9807class MultiTouchInputMapperTest_ExternalDevice : public MultiTouchInputMapperTest {
9808protected:
Chris Yea52ade12020-08-27 16:49:20 -07009809 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL); }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009810};
9811
9812/**
9813 * Expect fallback to internal viewport if device is external and external viewport is not present.
9814 */
9815TEST_F(MultiTouchInputMapperTest_ExternalDevice, Viewports_Fallback) {
9816 prepareAxes(POSITION);
9817 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009818 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00009819 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009820
9821 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
9822
9823 NotifyMotionArgs motionArgs;
9824
9825 // Expect the event to be sent to the internal viewport,
9826 // because an external viewport is not present.
9827 processPosition(mapper, 100, 100);
9828 processSync(mapper);
9829 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9830 ASSERT_EQ(ADISPLAY_ID_DEFAULT, motionArgs.displayId);
9831
9832 // Expect the event to be sent to the external viewport if it is present.
Michael Wrightfe3de7d2020-07-02 19:05:30 +01009833 prepareSecondaryDisplay(ViewportType::EXTERNAL);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009834 processPosition(mapper, 100, 100);
9835 processSync(mapper);
9836 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9837 ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
9838}
Arthur Hung4197f6b2020-03-16 15:39:59 +08009839
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009840TEST_F(MultiTouchInputMapperTest, Process_TouchpadCapture) {
9841 // we need a pointer controller for mouse mode of touchpad (start pointer at 0,0)
9842 std::shared_ptr<FakePointerController> fakePointerController =
9843 std::make_shared<FakePointerController>();
9844 fakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1);
9845 fakePointerController->setPosition(0, 0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009846
9847 // prepare device and capture
Michael Wrighta9cf4192022-12-01 23:46:39 +00009848 prepareDisplay(ui::ROTATION_0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009849 prepareAxes(POSITION | ID | SLOT);
9850 mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
9851 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
9852 mFakePolicy->setPointerCapture(true);
Prabir Pradhan2853b7a2021-08-23 14:08:51 +00009853 mFakePolicy->setPointerController(fakePointerController);
Arpit Singha8c236b2023-04-25 13:56:05 +00009854 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009855
9856 // captured touchpad should be a touchpad source
9857 NotifyDeviceResetArgs resetArgs;
9858 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
9859 ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
9860
Siarhei Vishniakou1983a712021-06-04 19:27:09 +00009861 InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
Chris Yef74dc422020-09-02 22:41:50 -07009862
9863 const InputDeviceInfo::MotionRange* relRangeX =
9864 deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_RELATIVE_X, AINPUT_SOURCE_TOUCHPAD);
9865 ASSERT_NE(relRangeX, nullptr);
9866 ASSERT_EQ(relRangeX->min, -(RAW_X_MAX - RAW_X_MIN));
9867 ASSERT_EQ(relRangeX->max, RAW_X_MAX - RAW_X_MIN);
9868 const InputDeviceInfo::MotionRange* relRangeY =
9869 deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_RELATIVE_Y, AINPUT_SOURCE_TOUCHPAD);
9870 ASSERT_NE(relRangeY, nullptr);
9871 ASSERT_EQ(relRangeY->min, -(RAW_Y_MAX - RAW_Y_MIN));
9872 ASSERT_EQ(relRangeY->max, RAW_Y_MAX - RAW_Y_MIN);
9873
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009874 // run captured pointer tests - note that this is unscaled, so input listener events should be
9875 // identical to what the hardware sends (accounting for any
9876 // calibration).
9877 // FINGER 0 DOWN
Chris Ye364fdb52020-08-05 15:07:56 -07009878 processSlot(mapper, 0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009879 processId(mapper, 1);
9880 processPosition(mapper, 100 + RAW_X_MIN, 100 + RAW_Y_MIN);
9881 processKey(mapper, BTN_TOUCH, 1);
9882 processSync(mapper);
9883
9884 // expect coord[0] to contain initial location of touch 0
9885 NotifyMotionArgs args;
9886 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9887 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009888 ASSERT_EQ(1U, args.getPointerCount());
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009889 ASSERT_EQ(0, args.pointerProperties[0].id);
9890 ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, args.source);
9891 ASSERT_NO_FATAL_FAILURE(
9892 assertPointerCoords(args.pointerCoords[0], 100, 100, 1, 0, 0, 0, 0, 0, 0, 0));
9893
9894 // FINGER 1 DOWN
9895 processSlot(mapper, 1);
9896 processId(mapper, 2);
9897 processPosition(mapper, 560 + RAW_X_MIN, 154 + RAW_Y_MIN);
9898 processSync(mapper);
9899
9900 // expect coord[0] to contain previous location, coord[1] to contain new touch 1 location
9901 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009902 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009903 ASSERT_EQ(2U, args.getPointerCount());
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009904 ASSERT_EQ(0, args.pointerProperties[0].id);
9905 ASSERT_EQ(1, args.pointerProperties[1].id);
9906 ASSERT_NO_FATAL_FAILURE(
9907 assertPointerCoords(args.pointerCoords[0], 100, 100, 1, 0, 0, 0, 0, 0, 0, 0));
9908 ASSERT_NO_FATAL_FAILURE(
9909 assertPointerCoords(args.pointerCoords[1], 560, 154, 1, 0, 0, 0, 0, 0, 0, 0));
9910
9911 // FINGER 1 MOVE
9912 processPosition(mapper, 540 + RAW_X_MIN, 690 + RAW_Y_MIN);
9913 processSync(mapper);
9914
9915 // expect coord[0] to contain previous location, coord[1] to contain new touch 1 location
9916 // from move
9917 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9918 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
9919 ASSERT_NO_FATAL_FAILURE(
9920 assertPointerCoords(args.pointerCoords[0], 100, 100, 1, 0, 0, 0, 0, 0, 0, 0));
9921 ASSERT_NO_FATAL_FAILURE(
9922 assertPointerCoords(args.pointerCoords[1], 540, 690, 1, 0, 0, 0, 0, 0, 0, 0));
9923
9924 // FINGER 0 MOVE
9925 processSlot(mapper, 0);
9926 processPosition(mapper, 50 + RAW_X_MIN, 800 + RAW_Y_MIN);
9927 processSync(mapper);
9928
9929 // expect coord[0] to contain new touch 0 location, coord[1] to contain previous location
9930 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9931 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
9932 ASSERT_NO_FATAL_FAILURE(
9933 assertPointerCoords(args.pointerCoords[0], 50, 800, 1, 0, 0, 0, 0, 0, 0, 0));
9934 ASSERT_NO_FATAL_FAILURE(
9935 assertPointerCoords(args.pointerCoords[1], 540, 690, 1, 0, 0, 0, 0, 0, 0, 0));
9936
9937 // BUTTON DOWN
9938 processKey(mapper, BTN_LEFT, 1);
9939 processSync(mapper);
9940
9941 // touchinputmapper design sends a move before button press
9942 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9943 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
9944 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9945 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, args.action);
9946
9947 // BUTTON UP
9948 processKey(mapper, BTN_LEFT, 0);
9949 processSync(mapper);
9950
9951 // touchinputmapper design sends a move after button release
9952 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9953 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, args.action);
9954 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9955 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
9956
9957 // FINGER 0 UP
9958 processId(mapper, -1);
9959 processSync(mapper);
9960 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9961 ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | 0x0000, args.action);
9962
9963 // FINGER 1 MOVE
9964 processSlot(mapper, 1);
9965 processPosition(mapper, 320 + RAW_X_MIN, 900 + RAW_Y_MIN);
9966 processSync(mapper);
9967
9968 // expect coord[0] to contain new location of touch 1, and properties[0].id to contain 1
9969 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9970 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009971 ASSERT_EQ(1U, args.getPointerCount());
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009972 ASSERT_EQ(1, args.pointerProperties[0].id);
9973 ASSERT_NO_FATAL_FAILURE(
9974 assertPointerCoords(args.pointerCoords[0], 320, 900, 1, 0, 0, 0, 0, 0, 0, 0));
9975
9976 // FINGER 1 UP
9977 processId(mapper, -1);
9978 processKey(mapper, BTN_TOUCH, 0);
9979 processSync(mapper);
9980 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9981 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
9982
Josep del Río2d8c79a2023-01-23 19:33:50 +00009983 // non captured touchpad should be a mouse source
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009984 mFakePolicy->setPointerCapture(false);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00009985 configureDevice(InputReaderConfiguration::Change::POINTER_CAPTURE);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009986 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Josep del Río2d8c79a2023-01-23 19:33:50 +00009987 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009988}
9989
9990TEST_F(MultiTouchInputMapperTest, Process_UnCapturedTouchpadPointer) {
9991 std::shared_ptr<FakePointerController> fakePointerController =
9992 std::make_shared<FakePointerController>();
9993 fakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1);
9994 fakePointerController->setPosition(0, 0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009995
9996 // prepare device and capture
Michael Wrighta9cf4192022-12-01 23:46:39 +00009997 prepareDisplay(ui::ROTATION_0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009998 prepareAxes(POSITION | ID | SLOT);
9999 mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
10000 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Prabir Pradhan2853b7a2021-08-23 14:08:51 +000010001 mFakePolicy->setPointerController(fakePointerController);
Arpit Singha8c236b2023-04-25 13:56:05 +000010002 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -080010003 // run uncaptured pointer tests - pushes out generic events
10004 // FINGER 0 DOWN
10005 processId(mapper, 3);
10006 processPosition(mapper, 100, 100);
10007 processKey(mapper, BTN_TOUCH, 1);
10008 processSync(mapper);
10009
10010 // start at (100,100), cursor should be at (0,0) * scale
10011 NotifyMotionArgs args;
10012 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
10013 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
10014 ASSERT_NO_FATAL_FAILURE(
10015 assertPointerCoords(args.pointerCoords[0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
10016
10017 // FINGER 0 MOVE
10018 processPosition(mapper, 200, 200);
10019 processSync(mapper);
10020
10021 // compute scaling to help with touch position checking
10022 float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
10023 float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
10024 float scale =
10025 mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
10026
10027 // translate from (100,100) -> (200,200), cursor should have changed to (100,100) * scale)
10028 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
10029 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
10030 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], 100 * scale, 100 * scale, 0,
10031 0, 0, 0, 0, 0, 0, 0));
LiZhihong758eb562022-11-03 15:28:29 +080010032
10033 // BUTTON DOWN
10034 processKey(mapper, BTN_LEFT, 1);
10035 processSync(mapper);
10036
10037 // touchinputmapper design sends a move before button press
10038 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
10039 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
10040 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
10041 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, args.action);
10042
10043 // BUTTON UP
10044 processKey(mapper, BTN_LEFT, 0);
10045 processSync(mapper);
10046
10047 // touchinputmapper design sends a move after button release
10048 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
10049 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, args.action);
10050 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
10051 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -080010052}
10053
10054TEST_F(MultiTouchInputMapperTest, WhenCapturedAndNotCaptured_GetSources) {
10055 std::shared_ptr<FakePointerController> fakePointerController =
10056 std::make_shared<FakePointerController>();
10057
Michael Wrighta9cf4192022-12-01 23:46:39 +000010058 prepareDisplay(ui::ROTATION_0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -080010059 prepareAxes(POSITION | ID | SLOT);
10060 mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
Prabir Pradhan2853b7a2021-08-23 14:08:51 +000010061 mFakePolicy->setPointerController(fakePointerController);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -080010062 mFakePolicy->setPointerCapture(false);
Arpit Singha8c236b2023-04-25 13:56:05 +000010063 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -080010064
Josep del Río2d8c79a2023-01-23 19:33:50 +000010065 // uncaptured touchpad should be a pointer device
10066 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -080010067
Josep del Río2d8c79a2023-01-23 19:33:50 +000010068 // captured touchpad should be a touchpad device
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -080010069 mFakePolicy->setPointerCapture(true);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +000010070 configureDevice(InputReaderConfiguration::Change::POINTER_CAPTURE);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -080010071 ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
10072}
10073
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +000010074// --- BluetoothMultiTouchInputMapperTest ---
10075
10076class BluetoothMultiTouchInputMapperTest : public MultiTouchInputMapperTest {
10077protected:
10078 void SetUp() override {
10079 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL, BUS_BLUETOOTH);
10080 }
10081};
10082
10083TEST_F(BluetoothMultiTouchInputMapperTest, TimestampSmoothening) {
10084 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +000010085 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +000010086 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +000010087 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +000010088
10089 nsecs_t kernelEventTime = ARBITRARY_TIME;
10090 nsecs_t expectedEventTime = ARBITRARY_TIME;
10091 // Touch down.
10092 processId(mapper, FIRST_TRACKING_ID);
10093 processPosition(mapper, 100, 200);
10094 processPressure(mapper, RAW_PRESSURE_MAX);
10095 processSync(mapper, ARBITRARY_TIME);
10096 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10097 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithEventTime(ARBITRARY_TIME))));
10098
10099 // Process several events that come in quick succession, according to their timestamps.
10100 for (int i = 0; i < 3; i++) {
10101 constexpr static nsecs_t delta = ms2ns(1);
10102 static_assert(delta < MIN_BLUETOOTH_TIMESTAMP_DELTA);
10103 kernelEventTime += delta;
10104 expectedEventTime += MIN_BLUETOOTH_TIMESTAMP_DELTA;
10105
10106 processPosition(mapper, 101 + i, 201 + i);
10107 processSync(mapper, kernelEventTime);
10108 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10109 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
10110 WithEventTime(expectedEventTime))));
10111 }
10112
10113 // Release the touch.
10114 processId(mapper, INVALID_TRACKING_ID);
10115 processPressure(mapper, RAW_PRESSURE_MIN);
10116 processSync(mapper, ARBITRARY_TIME + ms2ns(50));
10117 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10118 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
10119 WithEventTime(ARBITRARY_TIME + ms2ns(50)))));
10120}
10121
10122// --- MultiTouchPointerModeTest ---
10123
HQ Liue6983c72022-04-19 22:14:56 +000010124class MultiTouchPointerModeTest : public MultiTouchInputMapperTest {
10125protected:
10126 float mPointerMovementScale;
10127 float mPointerXZoomScale;
10128 void preparePointerMode(int xAxisResolution, int yAxisResolution) {
10129 addConfigurationProperty("touch.deviceType", "pointer");
10130 std::shared_ptr<FakePointerController> fakePointerController =
10131 std::make_shared<FakePointerController>();
10132 fakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1);
10133 fakePointerController->setPosition(0, 0);
Michael Wrighta9cf4192022-12-01 23:46:39 +000010134 prepareDisplay(ui::ROTATION_0);
HQ Liue6983c72022-04-19 22:14:56 +000010135
10136 prepareAxes(POSITION);
10137 prepareAbsoluteAxisResolution(xAxisResolution, yAxisResolution);
10138 // In order to enable swipe and freeform gesture in pointer mode, pointer capture
10139 // needs to be disabled, and the pointer gesture needs to be enabled.
10140 mFakePolicy->setPointerCapture(false);
10141 mFakePolicy->setPointerGestureEnabled(true);
10142 mFakePolicy->setPointerController(fakePointerController);
10143
10144 float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
10145 float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
10146 mPointerMovementScale =
10147 mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
10148 mPointerXZoomScale =
10149 mFakePolicy->getPointerGestureZoomSpeedRatio() * displayDiagonal / rawDiagonal;
10150 }
10151
10152 void prepareAbsoluteAxisResolution(int xAxisResolution, int yAxisResolution) {
10153 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX,
10154 /*flat*/ 0,
10155 /*fuzz*/ 0, /*resolution*/ xAxisResolution);
10156 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX,
10157 /*flat*/ 0,
10158 /*fuzz*/ 0, /*resolution*/ yAxisResolution);
10159 }
10160};
10161
10162/**
10163 * Two fingers down on a pointer mode touch pad. The width
10164 * of the two finger is larger than 1/4 of the touch pack diagnal length. However, it
10165 * is smaller than the fixed min physical length 30mm. Two fingers' distance must
10166 * be greater than the both value to be freeform gesture, so that after two
10167 * fingers start to move downwards, the gesture should be swipe.
10168 */
10169TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthSwipe) {
10170 // The min freeform gesture width is 25units/mm x 30mm = 750
10171 // which is greater than fraction of the diagnal length of the touchpad (349).
10172 // Thus, MaxSwipWidth is 750.
Harry Cutts33476232023-01-30 19:57:29 +000010173 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +000010174 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +000010175 NotifyMotionArgs motionArgs;
10176
10177 // Two fingers down at once.
10178 // The two fingers are 450 units apart, expects the current gesture to be PRESS
10179 // Pointer's initial position is used the [0,0] coordinate.
10180 int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125;
10181
10182 processId(mapper, FIRST_TRACKING_ID);
10183 processPosition(mapper, x1, y1);
10184 processMTSync(mapper);
10185 processId(mapper, SECOND_TRACKING_ID);
10186 processPosition(mapper, x2, y2);
10187 processMTSync(mapper);
10188 processSync(mapper);
10189
10190 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010191 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010192 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010193 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +000010194 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +000010195 ASSERT_NO_FATAL_FAILURE(
10196 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
10197
10198 // It should be recognized as a SWIPE gesture when two fingers start to move down,
10199 // that there should be 1 pointer.
10200 int32_t movingDistance = 200;
10201 y1 += movingDistance;
10202 y2 += movingDistance;
10203
10204 processId(mapper, FIRST_TRACKING_ID);
10205 processPosition(mapper, x1, y1);
10206 processMTSync(mapper);
10207 processId(mapper, SECOND_TRACKING_ID);
10208 processPosition(mapper, x2, y2);
10209 processMTSync(mapper);
10210 processSync(mapper);
10211
10212 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010213 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010214 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010215 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +000010216 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +000010217 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
10218 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
10219 0, 0, 0, 0));
10220}
10221
10222/**
10223 * Two fingers down on a pointer mode touch pad. The width of the two finger is larger
10224 * than the minimum freeform gesture width, 30mm. However, it is smaller than 1/4 of
10225 * the touch pack diagnal length. Two fingers' distance must be greater than the both
10226 * value to be freeform gesture, so that after two fingers start to move downwards,
10227 * the gesture should be swipe.
10228 */
10229TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthLowResolutionSwipe) {
10230 // The min freeform gesture width is 5units/mm x 30mm = 150
10231 // which is greater than fraction of the diagnal length of the touchpad (349).
10232 // Thus, MaxSwipWidth is the fraction of the diagnal length, 349.
Harry Cutts33476232023-01-30 19:57:29 +000010233 preparePointerMode(/*xResolution=*/5, /*yResolution=*/5);
Arpit Singha8c236b2023-04-25 13:56:05 +000010234 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +000010235 NotifyMotionArgs motionArgs;
10236
10237 // Two fingers down at once.
10238 // The two fingers are 250 units apart, expects the current gesture to be PRESS
10239 // Pointer's initial position is used the [0,0] coordinate.
10240 int32_t x1 = 100, y1 = 125, x2 = 350, y2 = 125;
10241
10242 processId(mapper, FIRST_TRACKING_ID);
10243 processPosition(mapper, x1, y1);
10244 processMTSync(mapper);
10245 processId(mapper, SECOND_TRACKING_ID);
10246 processPosition(mapper, x2, y2);
10247 processMTSync(mapper);
10248 processSync(mapper);
10249
10250 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010251 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010252 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010253 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +000010254 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +000010255 ASSERT_NO_FATAL_FAILURE(
10256 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
10257
10258 // It should be recognized as a SWIPE gesture when two fingers start to move down,
10259 // and there should be 1 pointer.
10260 int32_t movingDistance = 200;
10261 y1 += movingDistance;
10262 y2 += movingDistance;
10263
10264 processId(mapper, FIRST_TRACKING_ID);
10265 processPosition(mapper, x1, y1);
10266 processMTSync(mapper);
10267 processId(mapper, SECOND_TRACKING_ID);
10268 processPosition(mapper, x2, y2);
10269 processMTSync(mapper);
10270 processSync(mapper);
10271
10272 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010273 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010274 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010275 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +000010276 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +000010277 // New coordinate is the scaled relative coordinate from the initial coordinate.
10278 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
10279 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
10280 0, 0, 0, 0));
10281}
10282
10283/**
10284 * Touch the touch pad with two fingers with a distance wider than the minimum freeform
10285 * gesture width and 1/4 of the diagnal length of the touchpad. Expect to receive
10286 * freeform gestures after two fingers start to move downwards.
10287 */
10288TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthFreeform) {
Harry Cutts33476232023-01-30 19:57:29 +000010289 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +000010290 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +000010291
10292 NotifyMotionArgs motionArgs;
10293
10294 // Two fingers down at once. Wider than the max swipe width.
10295 // The gesture is expected to be PRESS, then transformed to FREEFORM
10296 int32_t x1 = 100, y1 = 125, x2 = 900, y2 = 125;
10297
10298 processId(mapper, FIRST_TRACKING_ID);
10299 processPosition(mapper, x1, y1);
10300 processMTSync(mapper);
10301 processId(mapper, SECOND_TRACKING_ID);
10302 processPosition(mapper, x2, y2);
10303 processMTSync(mapper);
10304 processSync(mapper);
10305
10306 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010307 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010308 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010309 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +000010310 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +000010311 // One pointer for PRESS, and its coordinate is used as the origin for pointer coordinates.
10312 ASSERT_NO_FATAL_FAILURE(
10313 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
10314
10315 int32_t movingDistance = 200;
10316
10317 // Move two fingers down, expect a cancel event because gesture is changing to freeform,
10318 // then two down events for two pointers.
10319 y1 += movingDistance;
10320 y2 += movingDistance;
10321
10322 processId(mapper, FIRST_TRACKING_ID);
10323 processPosition(mapper, x1, y1);
10324 processMTSync(mapper);
10325 processId(mapper, SECOND_TRACKING_ID);
10326 processPosition(mapper, x2, y2);
10327 processMTSync(mapper);
10328 processSync(mapper);
10329
10330 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
10331 // The previous PRESS gesture is cancelled, because it is transformed to freeform
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010332 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010333 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
10334 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010335 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010336 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010337 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
10338 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010339 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +000010340 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010341 ASSERT_EQ(2U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010342 ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN, motionArgs.action & AMOTION_EVENT_ACTION_MASK);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010343 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +000010344 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +000010345 // Two pointers' scaled relative coordinates from their initial centroid.
10346 // Initial y coordinates are 0 as y1 and y2 have the same value.
10347 float cookedX1 = (x1 - x2) / 2 * mPointerXZoomScale;
10348 float cookedX2 = (x2 - x1) / 2 * mPointerXZoomScale;
10349 // When pointers move, the new coordinates equal to the initial coordinates plus
10350 // scaled moving distance.
10351 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
10352 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
10353 0, 0, 0, 0));
10354 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], cookedX2,
10355 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
10356 0, 0, 0, 0));
10357
10358 // Move two fingers down again, expect one MOVE motion event.
10359 y1 += movingDistance;
10360 y2 += movingDistance;
10361
10362 processId(mapper, FIRST_TRACKING_ID);
10363 processPosition(mapper, x1, y1);
10364 processMTSync(mapper);
10365 processId(mapper, SECOND_TRACKING_ID);
10366 processPosition(mapper, x2, y2);
10367 processMTSync(mapper);
10368 processSync(mapper);
10369
10370 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010371 ASSERT_EQ(2U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +000010372 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010373 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +000010374 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +000010375 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
10376 movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
10377 0, 0, 0, 0, 0));
10378 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], cookedX2,
10379 movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
10380 0, 0, 0, 0, 0));
10381}
10382
Harry Cutts39b7ca22022-10-05 15:55:48 +000010383TEST_F(MultiTouchPointerModeTest, TwoFingerSwipeOffsets) {
Harry Cutts33476232023-01-30 19:57:29 +000010384 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +000010385 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Harry Cutts39b7ca22022-10-05 15:55:48 +000010386 NotifyMotionArgs motionArgs;
10387
10388 // Place two fingers down.
10389 int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125;
10390
10391 processId(mapper, FIRST_TRACKING_ID);
10392 processPosition(mapper, x1, y1);
10393 processMTSync(mapper);
10394 processId(mapper, SECOND_TRACKING_ID);
10395 processPosition(mapper, x2, y2);
10396 processMTSync(mapper);
10397 processSync(mapper);
10398
10399 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010400 ASSERT_EQ(1U, motionArgs.getPointerCount());
Harry Cutts39b7ca22022-10-05 15:55:48 +000010401 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
10402 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
10403 ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET));
10404 ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET));
10405
10406 // Move the two fingers down and to the left.
10407 int32_t movingDistance = 200;
10408 x1 -= movingDistance;
10409 y1 += movingDistance;
10410 x2 -= movingDistance;
10411 y2 += movingDistance;
10412
10413 processId(mapper, FIRST_TRACKING_ID);
10414 processPosition(mapper, x1, y1);
10415 processMTSync(mapper);
10416 processId(mapper, SECOND_TRACKING_ID);
10417 processPosition(mapper, x2, y2);
10418 processMTSync(mapper);
10419 processSync(mapper);
10420
10421 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010422 ASSERT_EQ(1U, motionArgs.getPointerCount());
Harry Cutts39b7ca22022-10-05 15:55:48 +000010423 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
10424 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
10425 ASSERT_LT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET), 0);
10426 ASSERT_GT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET), 0);
10427}
10428
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010429TEST_F(MultiTouchPointerModeTest, WhenViewportActiveStatusChanged_PointerGestureIsReset) {
Harry Cutts33476232023-01-30 19:57:29 +000010430 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010431 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +000010432 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010433 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
10434
10435 // Start a stylus gesture.
10436 processKey(mapper, BTN_TOOL_PEN, 1);
10437 processId(mapper, FIRST_TRACKING_ID);
10438 processPosition(mapper, 100, 200);
10439 processSync(mapper);
10440 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10441 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
10442 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010443 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010444 // TODO(b/257078296): Pointer mode generates extra event.
10445 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10446 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
10447 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010448 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010449 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
10450
10451 // Make the viewport inactive. This will put the device in disabled mode, and the ongoing stylus
10452 // gesture should be disabled.
10453 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
10454 viewport->isActive = false;
10455 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +000010456 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010457 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10458 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
10459 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010460 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010461 // TODO(b/257078296): Pointer mode generates extra event.
10462 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10463 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
10464 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010465 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010466 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
10467}
10468
Arthur Hung6d5b4b22022-01-21 07:21:10 +000010469// --- JoystickInputMapperTest ---
10470
10471class JoystickInputMapperTest : public InputMapperTest {
10472protected:
10473 static const int32_t RAW_X_MIN;
10474 static const int32_t RAW_X_MAX;
10475 static const int32_t RAW_Y_MIN;
10476 static const int32_t RAW_Y_MAX;
10477
10478 void SetUp() override {
10479 InputMapperTest::SetUp(InputDeviceClass::JOYSTICK | InputDeviceClass::EXTERNAL);
10480 }
10481 void prepareAxes() {
10482 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
10483 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
10484 }
10485
10486 void processAxis(JoystickInputMapper& mapper, int32_t axis, int32_t value) {
10487 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, axis, value);
10488 }
10489
10490 void processSync(JoystickInputMapper& mapper) {
10491 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
10492 }
10493
Michael Wrighta9cf4192022-12-01 23:46:39 +000010494 void prepareVirtualDisplay(ui::Rotation orientation) {
Arthur Hung6d5b4b22022-01-21 07:21:10 +000010495 setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH,
10496 VIRTUAL_DISPLAY_HEIGHT, orientation, VIRTUAL_DISPLAY_UNIQUE_ID,
10497 NO_PORT, ViewportType::VIRTUAL);
10498 }
10499};
10500
10501const int32_t JoystickInputMapperTest::RAW_X_MIN = -32767;
10502const int32_t JoystickInputMapperTest::RAW_X_MAX = 32767;
10503const int32_t JoystickInputMapperTest::RAW_Y_MIN = -32767;
10504const int32_t JoystickInputMapperTest::RAW_Y_MAX = 32767;
10505
10506TEST_F(JoystickInputMapperTest, Configure_AssignsDisplayUniqueId) {
10507 prepareAxes();
Arpit Singhae876352023-04-26 14:16:50 +000010508 JoystickInputMapper& mapper = constructAndAddMapper<JoystickInputMapper>();
Arthur Hung6d5b4b22022-01-21 07:21:10 +000010509
10510 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID);
10511
Michael Wrighta9cf4192022-12-01 23:46:39 +000010512 prepareVirtualDisplay(ui::ROTATION_0);
Arthur Hung6d5b4b22022-01-21 07:21:10 +000010513
10514 // Send an axis event
10515 processAxis(mapper, ABS_X, 100);
10516 processSync(mapper);
10517
10518 NotifyMotionArgs args;
10519 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
10520 ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId);
10521
10522 // Send another axis event
10523 processAxis(mapper, ABS_Y, 100);
10524 processSync(mapper);
10525
10526 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
10527 ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId);
10528}
10529
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010530// --- PeripheralControllerTest ---
Chris Yee2b1e5c2021-03-10 22:45:12 -080010531
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010532class PeripheralControllerTest : public testing::Test {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010533protected:
10534 static const char* DEVICE_NAME;
10535 static const char* DEVICE_LOCATION;
10536 static const int32_t DEVICE_ID;
10537 static const int32_t DEVICE_GENERATION;
10538 static const int32_t DEVICE_CONTROLLER_NUMBER;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010539 static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010540 static const int32_t EVENTHUB_ID;
10541
10542 std::shared_ptr<FakeEventHub> mFakeEventHub;
10543 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010544 std::unique_ptr<TestInputListener> mFakeListener;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010545 std::unique_ptr<InstrumentedInputReader> mReader;
10546 std::shared_ptr<InputDevice> mDevice;
10547
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010548 virtual void SetUp(ftl::Flags<InputDeviceClass> classes) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010549 mFakeEventHub = std::make_unique<FakeEventHub>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010550 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010551 mFakeListener = std::make_unique<TestInputListener>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010552 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010553 *mFakeListener);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010554 mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes);
10555 }
10556
10557 void SetUp() override { SetUp(DEVICE_CLASSES); }
10558
10559 void TearDown() override {
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010560 mFakeListener.reset();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010561 mFakePolicy.clear();
10562 }
10563
Chris Yee2b1e5c2021-03-10 22:45:12 -080010564 std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
10565 const std::string& location, int32_t eventHubId,
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010566 ftl::Flags<InputDeviceClass> classes) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010567 InputDeviceIdentifier identifier;
10568 identifier.name = name;
10569 identifier.location = location;
10570 std::shared_ptr<InputDevice> device =
10571 std::make_shared<InputDevice>(mReader->getContext(), deviceId, DEVICE_GENERATION,
10572 identifier);
10573 mReader->pushNextDevice(device);
10574 mFakeEventHub->addDevice(eventHubId, name, classes);
10575 mReader->loopOnce();
10576 return device;
10577 }
10578
10579 template <class T, typename... Args>
10580 T& addControllerAndConfigure(Args... args) {
10581 T& controller = mDevice->addController<T>(EVENTHUB_ID, args...);
10582
10583 return controller;
10584 }
10585};
10586
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010587const char* PeripheralControllerTest::DEVICE_NAME = "device";
10588const char* PeripheralControllerTest::DEVICE_LOCATION = "BLUETOOTH";
10589const int32_t PeripheralControllerTest::DEVICE_ID = END_RESERVED_ID + 1000;
10590const int32_t PeripheralControllerTest::DEVICE_GENERATION = 2;
10591const int32_t PeripheralControllerTest::DEVICE_CONTROLLER_NUMBER = 0;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010592const ftl::Flags<InputDeviceClass> PeripheralControllerTest::DEVICE_CLASSES =
10593 ftl::Flags<InputDeviceClass>(0); // not needed for current tests
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010594const int32_t PeripheralControllerTest::EVENTHUB_ID = 1;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010595
10596// --- BatteryControllerTest ---
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010597class BatteryControllerTest : public PeripheralControllerTest {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010598protected:
10599 void SetUp() override {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010600 PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::BATTERY);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010601 }
10602};
10603
10604TEST_F(BatteryControllerTest, GetBatteryCapacity) {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010605 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010606
Harry Cuttsa5b71292022-11-28 12:56:17 +000010607 ASSERT_TRUE(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY));
10608 ASSERT_EQ(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY).value_or(-1),
10609 FakeEventHub::BATTERY_CAPACITY);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010610}
10611
10612TEST_F(BatteryControllerTest, GetBatteryStatus) {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010613 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010614
Harry Cuttsa5b71292022-11-28 12:56:17 +000010615 ASSERT_TRUE(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY));
10616 ASSERT_EQ(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY).value_or(-1),
10617 FakeEventHub::BATTERY_STATUS);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010618}
10619
10620// --- LightControllerTest ---
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010621class LightControllerTest : public PeripheralControllerTest {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010622protected:
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010623 void SetUp() override {
10624 PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::LIGHT);
10625 }
Chris Yee2b1e5c2021-03-10 22:45:12 -080010626};
10627
Chris Ye85758332021-05-16 23:05:17 -070010628TEST_F(LightControllerTest, MonoLight) {
10629 RawLightInfo infoMono = {.id = 1,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010630 .name = "mono_light",
Chris Ye85758332021-05-16 23:05:17 -070010631 .maxBrightness = 255,
10632 .flags = InputLightClass::BRIGHTNESS,
10633 .path = ""};
10634 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010635
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010636 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010637 InputDeviceInfo info;
10638 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010639 std::vector<InputDeviceLightInfo> lights = info.getLights();
10640 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010641 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10642 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10643
10644 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_BRIGHTNESS));
10645 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_BRIGHTNESS);
10646}
10647
10648TEST_F(LightControllerTest, MonoKeyboardBacklight) {
10649 RawLightInfo infoMono = {.id = 1,
10650 .name = "mono_keyboard_backlight",
10651 .maxBrightness = 255,
10652 .flags = InputLightClass::BRIGHTNESS |
10653 InputLightClass::KEYBOARD_BACKLIGHT,
10654 .path = ""};
10655 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10656
10657 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10658 InputDeviceInfo info;
10659 controller.populateDeviceInfo(&info);
10660 std::vector<InputDeviceLightInfo> lights = info.getLights();
10661 ASSERT_EQ(1U, lights.size());
10662 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10663 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010664
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010665 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_BRIGHTNESS));
10666 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_BRIGHTNESS);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010667}
10668
Vaibhav Devmurari16c24192023-05-04 15:20:12 +000010669TEST_F(LightControllerTest, Ignore_MonoLight_WithPreferredBacklightLevels) {
10670 RawLightInfo infoMono = {.id = 1,
10671 .name = "mono_light",
10672 .maxBrightness = 255,
10673 .flags = InputLightClass::BRIGHTNESS,
10674 .path = ""};
10675 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10676 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10677 "0,100,200");
10678
10679 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10680 std::list<NotifyArgs> unused =
10681 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10682 /*changes=*/{});
10683
10684 InputDeviceInfo info;
10685 controller.populateDeviceInfo(&info);
10686 std::vector<InputDeviceLightInfo> lights = info.getLights();
10687 ASSERT_EQ(1U, lights.size());
10688 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10689}
10690
10691TEST_F(LightControllerTest, KeyboardBacklight_WithNoPreferredBacklightLevels) {
10692 RawLightInfo infoMono = {.id = 1,
10693 .name = "mono_keyboard_backlight",
10694 .maxBrightness = 255,
10695 .flags = InputLightClass::BRIGHTNESS |
10696 InputLightClass::KEYBOARD_BACKLIGHT,
10697 .path = ""};
10698 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10699
10700 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10701 std::list<NotifyArgs> unused =
10702 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10703 /*changes=*/{});
10704
10705 InputDeviceInfo info;
10706 controller.populateDeviceInfo(&info);
10707 std::vector<InputDeviceLightInfo> lights = info.getLights();
10708 ASSERT_EQ(1U, lights.size());
10709 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10710}
10711
10712TEST_F(LightControllerTest, KeyboardBacklight_WithPreferredBacklightLevels) {
10713 RawLightInfo infoMono = {.id = 1,
10714 .name = "mono_keyboard_backlight",
10715 .maxBrightness = 255,
10716 .flags = InputLightClass::BRIGHTNESS |
10717 InputLightClass::KEYBOARD_BACKLIGHT,
10718 .path = ""};
10719 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10720 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10721 "0,100,200");
10722
10723 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10724 std::list<NotifyArgs> unused =
10725 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10726 /*changes=*/{});
10727
10728 InputDeviceInfo info;
10729 controller.populateDeviceInfo(&info);
10730 std::vector<InputDeviceLightInfo> lights = info.getLights();
10731 ASSERT_EQ(1U, lights.size());
10732 ASSERT_EQ(3U, lights[0].preferredBrightnessLevels.size());
10733 std::set<BrightnessLevel>::iterator it = lights[0].preferredBrightnessLevels.begin();
10734 ASSERT_EQ(BrightnessLevel(0), *it);
10735 std::advance(it, 1);
10736 ASSERT_EQ(BrightnessLevel(100), *it);
10737 std::advance(it, 1);
10738 ASSERT_EQ(BrightnessLevel(200), *it);
10739}
10740
10741TEST_F(LightControllerTest, KeyboardBacklight_WithWrongPreferredBacklightLevels) {
10742 RawLightInfo infoMono = {.id = 1,
10743 .name = "mono_keyboard_backlight",
10744 .maxBrightness = 255,
10745 .flags = InputLightClass::BRIGHTNESS |
10746 InputLightClass::KEYBOARD_BACKLIGHT,
10747 .path = ""};
10748 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10749 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10750 "0,100,200,300,400,500");
10751
10752 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10753 std::list<NotifyArgs> unused =
10754 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10755 /*changes=*/{});
10756
10757 InputDeviceInfo info;
10758 controller.populateDeviceInfo(&info);
10759 std::vector<InputDeviceLightInfo> lights = info.getLights();
10760 ASSERT_EQ(1U, lights.size());
10761 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10762}
10763
Chris Yee2b1e5c2021-03-10 22:45:12 -080010764TEST_F(LightControllerTest, RGBLight) {
10765 RawLightInfo infoRed = {.id = 1,
10766 .name = "red",
10767 .maxBrightness = 255,
10768 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED,
10769 .path = ""};
10770 RawLightInfo infoGreen = {.id = 2,
10771 .name = "green",
10772 .maxBrightness = 255,
10773 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN,
10774 .path = ""};
10775 RawLightInfo infoBlue = {.id = 3,
10776 .name = "blue",
10777 .maxBrightness = 255,
10778 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE,
10779 .path = ""};
10780 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10781 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10782 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10783
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010784 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010785 InputDeviceInfo info;
10786 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010787 std::vector<InputDeviceLightInfo> lights = info.getLights();
10788 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010789 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10790 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10791 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10792
10793 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10794 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10795}
10796
10797TEST_F(LightControllerTest, CorrectRGBKeyboardBacklight) {
10798 RawLightInfo infoRed = {.id = 1,
10799 .name = "red_keyboard_backlight",
10800 .maxBrightness = 255,
10801 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED |
10802 InputLightClass::KEYBOARD_BACKLIGHT,
10803 .path = ""};
10804 RawLightInfo infoGreen = {.id = 2,
10805 .name = "green_keyboard_backlight",
10806 .maxBrightness = 255,
10807 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN |
10808 InputLightClass::KEYBOARD_BACKLIGHT,
10809 .path = ""};
10810 RawLightInfo infoBlue = {.id = 3,
10811 .name = "blue_keyboard_backlight",
10812 .maxBrightness = 255,
10813 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE |
10814 InputLightClass::KEYBOARD_BACKLIGHT,
10815 .path = ""};
10816 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10817 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10818 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10819
10820 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10821 InputDeviceInfo info;
10822 controller.populateDeviceInfo(&info);
10823 std::vector<InputDeviceLightInfo> lights = info.getLights();
10824 ASSERT_EQ(1U, lights.size());
10825 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10826 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10827 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10828
10829 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10830 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10831}
10832
10833TEST_F(LightControllerTest, IncorrectRGBKeyboardBacklight) {
10834 RawLightInfo infoRed = {.id = 1,
10835 .name = "red",
10836 .maxBrightness = 255,
10837 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED,
10838 .path = ""};
10839 RawLightInfo infoGreen = {.id = 2,
10840 .name = "green",
10841 .maxBrightness = 255,
10842 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN,
10843 .path = ""};
10844 RawLightInfo infoBlue = {.id = 3,
10845 .name = "blue",
10846 .maxBrightness = 255,
10847 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE,
10848 .path = ""};
10849 RawLightInfo infoGlobal = {.id = 3,
10850 .name = "global_keyboard_backlight",
10851 .maxBrightness = 255,
10852 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GLOBAL |
10853 InputLightClass::KEYBOARD_BACKLIGHT,
10854 .path = ""};
10855 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10856 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10857 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10858 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoGlobal));
10859
10860 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10861 InputDeviceInfo info;
10862 controller.populateDeviceInfo(&info);
10863 std::vector<InputDeviceLightInfo> lights = info.getLights();
10864 ASSERT_EQ(1U, lights.size());
10865 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10866 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10867 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010868
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010869 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10870 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010871}
10872
10873TEST_F(LightControllerTest, MultiColorRGBLight) {
10874 RawLightInfo infoColor = {.id = 1,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010875 .name = "multi_color",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010876 .maxBrightness = 255,
10877 .flags = InputLightClass::BRIGHTNESS |
10878 InputLightClass::MULTI_INTENSITY |
10879 InputLightClass::MULTI_INDEX,
10880 .path = ""};
10881
10882 mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
10883
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010884 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010885 InputDeviceInfo info;
10886 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010887 std::vector<InputDeviceLightInfo> lights = info.getLights();
10888 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010889 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10890 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10891 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10892
10893 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10894 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10895}
10896
10897TEST_F(LightControllerTest, MultiColorRGBKeyboardBacklight) {
10898 RawLightInfo infoColor = {.id = 1,
10899 .name = "multi_color_keyboard_backlight",
10900 .maxBrightness = 255,
10901 .flags = InputLightClass::BRIGHTNESS |
10902 InputLightClass::MULTI_INTENSITY |
10903 InputLightClass::MULTI_INDEX |
10904 InputLightClass::KEYBOARD_BACKLIGHT,
10905 .path = ""};
10906
10907 mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
10908
10909 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10910 InputDeviceInfo info;
10911 controller.populateDeviceInfo(&info);
10912 std::vector<InputDeviceLightInfo> lights = info.getLights();
10913 ASSERT_EQ(1U, lights.size());
10914 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10915 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10916 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010917
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010918 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10919 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010920}
10921
10922TEST_F(LightControllerTest, PlayerIdLight) {
10923 RawLightInfo info1 = {.id = 1,
10924 .name = "player1",
10925 .maxBrightness = 255,
10926 .flags = InputLightClass::BRIGHTNESS,
10927 .path = ""};
10928 RawLightInfo info2 = {.id = 2,
10929 .name = "player2",
10930 .maxBrightness = 255,
10931 .flags = InputLightClass::BRIGHTNESS,
10932 .path = ""};
10933 RawLightInfo info3 = {.id = 3,
10934 .name = "player3",
10935 .maxBrightness = 255,
10936 .flags = InputLightClass::BRIGHTNESS,
10937 .path = ""};
10938 RawLightInfo info4 = {.id = 4,
10939 .name = "player4",
10940 .maxBrightness = 255,
10941 .flags = InputLightClass::BRIGHTNESS,
10942 .path = ""};
10943 mFakeEventHub->addRawLightInfo(info1.id, std::move(info1));
10944 mFakeEventHub->addRawLightInfo(info2.id, std::move(info2));
10945 mFakeEventHub->addRawLightInfo(info3.id, std::move(info3));
10946 mFakeEventHub->addRawLightInfo(info4.id, std::move(info4));
10947
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010948 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010949 InputDeviceInfo info;
10950 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010951 std::vector<InputDeviceLightInfo> lights = info.getLights();
10952 ASSERT_EQ(1U, lights.size());
10953 ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010954 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10955 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010956
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010957 ASSERT_FALSE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10958 ASSERT_TRUE(controller.setLightPlayerId(lights[0].id, LIGHT_PLAYER_ID));
10959 ASSERT_EQ(controller.getLightPlayerId(lights[0].id).value_or(-1), LIGHT_PLAYER_ID);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010960}
10961
Michael Wrightd02c5b62014-02-10 15:10:22 -080010962} // namespace android