blob: 17c37d5a41c29a7d2edcf099549bc61bf84d503f [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>
Prabir Pradhan2770d242019-09-02 18:07:11 -070027#include <KeyboardInputMapper.h>
28#include <MultiTouchInputMapper.h>
Prabir Pradhan018faea2024-05-08 21:52:54 +000029#include <NotifyArgsBuilders.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>
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000033#include <TestEventMatchers.h>
Prabir Pradhan2770d242019-09-02 18:07:11 -070034#include <TestInputListener.h>
35#include <TouchInputMapper.h>
Prabir Pradhan1aed8582019-12-30 11:46:51 -080036#include <UinputDevice.h>
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070037#include <android-base/thread_annotations.h>
Byoungho Jungda10dd32023-10-06 17:03:45 +090038#include <com_android_input_flags.h>
Michael Wrighta9cf4192022-12-01 23:46:39 +000039#include <ftl/enum.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080040#include <gtest/gtest.h>
Michael Wrighta9cf4192022-12-01 23:46:39 +000041#include <ui/Rotation.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080042
Siarhei Vishniakou21e96e62022-10-27 10:23:37 -070043#include <thread>
Harry Cuttsa5b71292022-11-28 12:56:17 +000044#include "FakeEventHub.h"
Harry Cutts6b5fbc52022-11-28 16:37:43 +000045#include "FakeInputReaderPolicy.h"
Harry Cuttse6512e12022-11-28 18:44:01 +000046#include "InputMapperTest.h"
Harry Cutts144ff542022-11-28 17:41:06 +000047#include "InstrumentedInputReader.h"
Harry Cuttsa5b71292022-11-28 12:56:17 +000048#include "TestConstants.h"
Michael Wrightdde67b82020-10-27 16:09:22 +000049#include "input/DisplayViewport.h"
50#include "input/Input.h"
Michael Wright17db18e2020-06-26 20:51:44 +010051
Michael Wrightd02c5b62014-02-10 15:10:22 -080052namespace android {
53
Dominik Laskowski2f01d772022-03-23 16:01:29 -070054using namespace ftl::flag_operators;
Prabir Pradhan739dca42022-09-09 20:12:01 +000055using testing::AllOf;
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +000056using testing::VariantWith;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070057using std::chrono_literals::operator""ms;
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -080058using std::chrono_literals::operator""s;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070059
Michael Wrightd02c5b62014-02-10 15:10:22 -080060// Arbitrary display properties.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070061static constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhanc13ff082022-09-08 22:03:30 +000062static const std::string DISPLAY_UNIQUE_ID = "local:1";
Linnan Li13bf76a2024-05-05 19:18:02 +080063static constexpr ui::LogicalDisplayId SECONDARY_DISPLAY_ID =
64 ui::LogicalDisplayId{DISPLAY_ID.val() + 1};
arthurhungcc7f9802020-04-30 17:55:40 +080065static constexpr int32_t DISPLAY_WIDTH = 480;
66static constexpr int32_t DISPLAY_HEIGHT = 800;
Linnan Li13bf76a2024-05-05 19:18:02 +080067static constexpr ui::LogicalDisplayId VIRTUAL_DISPLAY_ID = ui::LogicalDisplayId{1};
arthurhungcc7f9802020-04-30 17:55:40 +080068static constexpr int32_t VIRTUAL_DISPLAY_WIDTH = 400;
69static constexpr int32_t VIRTUAL_DISPLAY_HEIGHT = 500;
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -070070static const char* VIRTUAL_DISPLAY_UNIQUE_ID = "virtual:1";
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -070071static constexpr std::optional<uint8_t> NO_PORT = std::nullopt; // no physical port is specified
Michael Wrightd02c5b62014-02-10 15:10:22 -080072
arthurhungcc7f9802020-04-30 17:55:40 +080073static constexpr int32_t FIRST_SLOT = 0;
74static constexpr int32_t SECOND_SLOT = 1;
75static constexpr int32_t THIRD_SLOT = 2;
76static constexpr int32_t INVALID_TRACKING_ID = -1;
77static constexpr int32_t FIRST_TRACKING_ID = 0;
78static constexpr int32_t SECOND_TRACKING_ID = 1;
79static constexpr int32_t THIRD_TRACKING_ID = 2;
Chris Ye3fdbfef2021-01-06 18:45:18 -080080static constexpr int32_t LIGHT_BRIGHTNESS = 0x55000000;
81static constexpr int32_t LIGHT_COLOR = 0x7F448866;
82static constexpr int32_t LIGHT_PLAYER_ID = 2;
arthurhungcc7f9802020-04-30 17:55:40 +080083
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -080084static constexpr int32_t ACTION_POINTER_0_DOWN =
85 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
86static constexpr int32_t ACTION_POINTER_0_UP =
87 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
88static constexpr int32_t ACTION_POINTER_1_DOWN =
89 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
90static constexpr int32_t ACTION_POINTER_1_UP =
91 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
92
Prabir Pradhanb08a0e82023-09-14 22:28:32 +000093static constexpr uint32_t STYLUS_FUSION_SOURCE =
94 AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_BLUETOOTH_STYLUS;
95
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +000096// Minimum timestamp separation between subsequent input events from a Bluetooth device.
97static constexpr nsecs_t MIN_BLUETOOTH_TIMESTAMP_DELTA = ms2ns(4);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +000098
Byoungho Jungda10dd32023-10-06 17:03:45 +090099namespace input_flags = com::android::input::flags;
100
Michael Wrightd02c5b62014-02-10 15:10:22 -0800101template<typename T>
102static inline T min(T a, T b) {
103 return a < b ? a : b;
104}
105
106static inline float avg(float x, float y) {
107 return (x + y) / 2;
108}
109
Chris Ye3fdbfef2021-01-06 18:45:18 -0800110// Mapping for light color name and the light color
111const std::unordered_map<std::string, LightColor> LIGHT_COLORS = {{"red", LightColor::RED},
112 {"green", LightColor::GREEN},
113 {"blue", LightColor::BLUE}};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800114
Michael Wrighta9cf4192022-12-01 23:46:39 +0000115static ui::Rotation getInverseRotation(ui::Rotation orientation) {
Prabir Pradhanc14266f2021-05-12 15:56:24 -0700116 switch (orientation) {
Michael Wrighta9cf4192022-12-01 23:46:39 +0000117 case ui::ROTATION_90:
118 return ui::ROTATION_270;
119 case ui::ROTATION_270:
120 return ui::ROTATION_90;
Prabir Pradhanc14266f2021-05-12 15:56:24 -0700121 default:
122 return orientation;
123 }
124}
125
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800126static void assertAxisResolution(MultiTouchInputMapper& mapper, int axis, float resolution) {
127 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +0000128 mapper.populateDeviceInfo(info);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800129
130 const InputDeviceInfo::MotionRange* motionRange =
131 info.getMotionRange(axis, AINPUT_SOURCE_TOUCHSCREEN);
132 ASSERT_NEAR(motionRange->resolution, resolution, EPSILON);
133}
134
135static void assertAxisNotPresent(MultiTouchInputMapper& mapper, int axis) {
136 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +0000137 mapper.populateDeviceInfo(info);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800138
139 const InputDeviceInfo::MotionRange* motionRange =
140 info.getMotionRange(axis, AINPUT_SOURCE_TOUCHSCREEN);
141 ASSERT_EQ(nullptr, motionRange);
142}
143
Siarhei Vishniakou21e96e62022-10-27 10:23:37 -0700144[[maybe_unused]] static void dumpReader(InputReader& reader) {
145 std::string dump;
146 reader.dump(dump);
147 std::istringstream iss(dump);
148 for (std::string line; std::getline(iss, line);) {
149 ALOGE("%s", line.c_str());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -0800150 std::this_thread::sleep_for(1ms);
Siarhei Vishniakou21e96e62022-10-27 10:23:37 -0700151 }
152}
153
Michael Wrightd02c5b62014-02-10 15:10:22 -0800154// --- FakeInputMapper ---
155
156class FakeInputMapper : public InputMapper {
157 uint32_t mSources;
158 int32_t mKeyboardType;
159 int32_t mMetaState;
160 KeyedVector<int32_t, int32_t> mKeyCodeStates;
161 KeyedVector<int32_t, int32_t> mScanCodeStates;
162 KeyedVector<int32_t, int32_t> mSwitchStates;
Philip Junker4af3b3d2021-12-14 10:36:55 +0100163 // fake mapping which would normally come from keyCharacterMap
164 std::unordered_map<int32_t, int32_t> mKeyCodeMapping;
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800165 std::vector<int32_t> mSupportedKeyCodes;
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700166 std::list<NotifyArgs> mProcessResult;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800167
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700168 std::mutex mLock;
169 std::condition_variable mStateChangedCondition;
170 bool mConfigureWasCalled GUARDED_BY(mLock);
171 bool mResetWasCalled GUARDED_BY(mLock);
172 bool mProcessWasCalled GUARDED_BY(mLock);
173 RawEvent mLastEvent GUARDED_BY(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800174
Arthur Hungc23540e2018-11-29 20:42:11 +0800175 std::optional<DisplayViewport> mViewport;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800176public:
Arpit Singh8e6fb252023-04-06 11:49:17 +0000177 FakeInputMapper(InputDeviceContext& deviceContext, const InputReaderConfiguration& readerConfig,
178 uint32_t sources)
179 : InputMapper(deviceContext, readerConfig),
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800180 mSources(sources),
181 mKeyboardType(AINPUT_KEYBOARD_TYPE_NONE),
Michael Wrightd02c5b62014-02-10 15:10:22 -0800182 mMetaState(0),
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800183 mConfigureWasCalled(false),
184 mResetWasCalled(false),
185 mProcessWasCalled(false) {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800186
Chris Yea52ade12020-08-27 16:49:20 -0700187 virtual ~FakeInputMapper() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800188
189 void setKeyboardType(int32_t keyboardType) {
190 mKeyboardType = keyboardType;
191 }
192
193 void setMetaState(int32_t metaState) {
194 mMetaState = metaState;
195 }
196
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700197 // Sets the return value for the `process` call.
198 void setProcessResult(std::list<NotifyArgs> notifyArgs) {
199 mProcessResult.clear();
200 for (auto notifyArg : notifyArgs) {
201 mProcessResult.push_back(notifyArg);
202 }
203 }
204
Michael Wrightd02c5b62014-02-10 15:10:22 -0800205 void assertConfigureWasCalled() {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700206 std::unique_lock<std::mutex> lock(mLock);
207 base::ScopedLockAssertion assumeLocked(mLock);
208 const bool configureCalled =
209 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
210 return mConfigureWasCalled;
211 });
212 if (!configureCalled) {
213 FAIL() << "Expected configure() to have been called.";
214 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800215 mConfigureWasCalled = false;
216 }
217
218 void assertResetWasCalled() {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700219 std::unique_lock<std::mutex> lock(mLock);
220 base::ScopedLockAssertion assumeLocked(mLock);
221 const bool resetCalled =
222 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
223 return mResetWasCalled;
224 });
225 if (!resetCalled) {
226 FAIL() << "Expected reset() to have been called.";
227 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800228 mResetWasCalled = false;
229 }
230
Prabir Pradhanf8d9e442023-12-06 22:06:13 +0000231 void assertResetWasNotCalled() {
232 std::scoped_lock lock(mLock);
233 ASSERT_FALSE(mResetWasCalled) << "Expected reset to not have been called.";
234 }
235
Yi Kong9b14ac62018-07-17 13:48:38 -0700236 void assertProcessWasCalled(RawEvent* outLastEvent = nullptr) {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700237 std::unique_lock<std::mutex> lock(mLock);
238 base::ScopedLockAssertion assumeLocked(mLock);
239 const bool processCalled =
240 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
241 return mProcessWasCalled;
242 });
243 if (!processCalled) {
244 FAIL() << "Expected process() to have been called.";
245 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800246 if (outLastEvent) {
247 *outLastEvent = mLastEvent;
248 }
249 mProcessWasCalled = false;
250 }
251
Prabir Pradhanf8d9e442023-12-06 22:06:13 +0000252 void assertProcessWasNotCalled() {
253 std::scoped_lock lock(mLock);
254 ASSERT_FALSE(mProcessWasCalled) << "Expected process to not have been called.";
255 }
256
Michael Wrightd02c5b62014-02-10 15:10:22 -0800257 void setKeyCodeState(int32_t keyCode, int32_t state) {
258 mKeyCodeStates.replaceValueFor(keyCode, state);
259 }
260
261 void setScanCodeState(int32_t scanCode, int32_t state) {
262 mScanCodeStates.replaceValueFor(scanCode, state);
263 }
264
265 void setSwitchState(int32_t switchCode, int32_t state) {
266 mSwitchStates.replaceValueFor(switchCode, state);
267 }
268
269 void addSupportedKeyCode(int32_t keyCode) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800270 mSupportedKeyCodes.push_back(keyCode);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800271 }
272
Philip Junker4af3b3d2021-12-14 10:36:55 +0100273 void addKeyCodeMapping(int32_t fromKeyCode, int32_t toKeyCode) {
274 mKeyCodeMapping.insert_or_assign(fromKeyCode, toKeyCode);
275 }
276
Michael Wrightd02c5b62014-02-10 15:10:22 -0800277private:
Philip Junker4af3b3d2021-12-14 10:36:55 +0100278 uint32_t getSources() const override { return mSources; }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800279
Harry Cuttsd02ea102023-03-17 18:21:30 +0000280 void populateDeviceInfo(InputDeviceInfo& deviceInfo) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800281 InputMapper::populateDeviceInfo(deviceInfo);
282
283 if (mKeyboardType != AINPUT_KEYBOARD_TYPE_NONE) {
Harry Cuttsd02ea102023-03-17 18:21:30 +0000284 deviceInfo.setKeyboardType(mKeyboardType);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800285 }
286 }
287
Arpit Singhed6c3de2023-04-05 19:24:37 +0000288 std::list<NotifyArgs> reconfigure(nsecs_t, const InputReaderConfiguration& config,
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000289 ConfigurationChanges changes) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700290 std::scoped_lock<std::mutex> lock(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800291 mConfigureWasCalled = true;
Arthur Hungc23540e2018-11-29 20:42:11 +0800292
293 // Find the associated viewport if exist.
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800294 const std::optional<uint8_t> displayPort = getDeviceContext().getAssociatedDisplayPort();
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000295 if (displayPort && changes.test(InputReaderConfiguration::Change::DISPLAY_INFO)) {
Arpit Singhed6c3de2023-04-05 19:24:37 +0000296 mViewport = config.getDisplayViewportByPort(*displayPort);
Arthur Hungc23540e2018-11-29 20:42:11 +0800297 }
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700298
299 mStateChangedCondition.notify_all();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700300 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800301 }
302
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700303 std::list<NotifyArgs> reset(nsecs_t) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700304 std::scoped_lock<std::mutex> lock(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800305 mResetWasCalled = true;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700306 mStateChangedCondition.notify_all();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700307 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800308 }
309
Harry Cuttsa32a1192024-06-04 15:10:31 +0000310 std::list<NotifyArgs> process(const RawEvent& rawEvent) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700311 std::scoped_lock<std::mutex> lock(mLock);
Harry Cuttsa32a1192024-06-04 15:10:31 +0000312 mLastEvent = rawEvent;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800313 mProcessWasCalled = true;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700314 mStateChangedCondition.notify_all();
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700315 return mProcessResult;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800316 }
317
Chris Yea52ade12020-08-27 16:49:20 -0700318 int32_t getKeyCodeState(uint32_t, int32_t keyCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800319 ssize_t index = mKeyCodeStates.indexOfKey(keyCode);
320 return index >= 0 ? mKeyCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
321 }
322
Philip Junker4af3b3d2021-12-14 10:36:55 +0100323 int32_t getKeyCodeForKeyLocation(int32_t locationKeyCode) const override {
324 auto it = mKeyCodeMapping.find(locationKeyCode);
325 return it != mKeyCodeMapping.end() ? it->second : locationKeyCode;
326 }
327
Chris Yea52ade12020-08-27 16:49:20 -0700328 int32_t getScanCodeState(uint32_t, int32_t scanCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800329 ssize_t index = mScanCodeStates.indexOfKey(scanCode);
330 return index >= 0 ? mScanCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
331 }
332
Chris Yea52ade12020-08-27 16:49:20 -0700333 int32_t getSwitchState(uint32_t, int32_t switchCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800334 ssize_t index = mSwitchStates.indexOfKey(switchCode);
335 return index >= 0 ? mSwitchStates.valueAt(index) : AKEY_STATE_UNKNOWN;
336 }
337
Chris Yea52ade12020-08-27 16:49:20 -0700338 // Return true if the device has non-empty key layout.
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700339 bool markSupportedKeyCodes(uint32_t, const std::vector<int32_t>& keyCodes,
Chris Yea52ade12020-08-27 16:49:20 -0700340 uint8_t* outFlags) override {
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700341 for (size_t i = 0; i < keyCodes.size(); i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800342 for (size_t j = 0; j < mSupportedKeyCodes.size(); j++) {
343 if (keyCodes[i] == mSupportedKeyCodes[j]) {
344 outFlags[i] = 1;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800345 }
346 }
347 }
Chris Yea52ade12020-08-27 16:49:20 -0700348 bool result = mSupportedKeyCodes.size() > 0;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800349 return result;
350 }
351
352 virtual int32_t getMetaState() {
353 return mMetaState;
354 }
355
356 virtual void fadePointer() {
357 }
Arthur Hungc23540e2018-11-29 20:42:11 +0800358
Linnan Li13bf76a2024-05-05 19:18:02 +0800359 virtual std::optional<ui::LogicalDisplayId> getAssociatedDisplay() {
Arthur Hungc23540e2018-11-29 20:42:11 +0800360 if (mViewport) {
361 return std::make_optional(mViewport->displayId);
362 }
363 return std::nullopt;
364 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800365};
366
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700367// --- InputReaderPolicyTest ---
368class InputReaderPolicyTest : public testing::Test {
Siarhei Vishniakoucd7ac1e2018-10-15 13:39:50 -0700369protected:
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700370 sp<FakeInputReaderPolicy> mFakePolicy;
371
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700372 void SetUp() override { mFakePolicy = sp<FakeInputReaderPolicy>::make(); }
Chris Yea52ade12020-08-27 16:49:20 -0700373 void TearDown() override { mFakePolicy.clear(); }
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700374};
375
376/**
377 * Check that empty set of viewports is an acceptable configuration.
378 * Also try to get internal viewport two different ways - by type and by uniqueId.
379 *
380 * There will be confusion if two viewports with empty uniqueId and identical type are present.
381 * Such configuration is not currently allowed.
382 */
383TEST_F(InputReaderPolicyTest, Viewports_GetCleared) {
Siarhei Vishniakoucd7ac1e2018-10-15 13:39:50 -0700384 static const std::string uniqueId = "local:0";
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700385
386 // We didn't add any viewports yet, so there shouldn't be any.
387 std::optional<DisplayViewport> internalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100388 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700389 ASSERT_FALSE(internalViewport);
390
391 // Add an internal viewport, then clear it
Michael Wrighta9cf4192022-12-01 23:46:39 +0000392 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000393 /*isActive=*/true, uniqueId, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700394
395 // Check matching by uniqueId
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700396 internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700397 ASSERT_TRUE(internalViewport);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100398 ASSERT_EQ(ViewportType::INTERNAL, internalViewport->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700399
400 // Check matching by viewport type
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100401 internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700402 ASSERT_TRUE(internalViewport);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700403 ASSERT_EQ(uniqueId, internalViewport->uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700404
405 mFakePolicy->clearViewports();
406 // Make sure nothing is found after clear
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700407 internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700408 ASSERT_FALSE(internalViewport);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100409 internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700410 ASSERT_FALSE(internalViewport);
411}
412
413TEST_F(InputReaderPolicyTest, Viewports_GetByType) {
414 const std::string internalUniqueId = "local:0";
415 const std::string externalUniqueId = "local:1";
416 const std::string virtualUniqueId1 = "virtual:2";
417 const std::string virtualUniqueId2 = "virtual:3";
Linnan Li13bf76a2024-05-05 19:18:02 +0800418 constexpr ui::LogicalDisplayId virtualDisplayId1 = ui::LogicalDisplayId{2};
419 constexpr ui::LogicalDisplayId virtualDisplayId2 = ui::LogicalDisplayId{3};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700420
421 // Add an internal viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000422 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000423 /*isActive=*/true, internalUniqueId, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000424 ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700425 // Add an external 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, externalUniqueId, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000428 ViewportType::EXTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700429 // Add an virtual viewport
430 mFakePolicy->addDisplayViewport(virtualDisplayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000431 ui::ROTATION_0, /*isActive=*/true, virtualUniqueId1, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000432 ViewportType::VIRTUAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700433 // Add another virtual viewport
434 mFakePolicy->addDisplayViewport(virtualDisplayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000435 ui::ROTATION_0, /*isActive=*/true, virtualUniqueId2, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000436 ViewportType::VIRTUAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700437
438 // Check matching by type for internal
439 std::optional<DisplayViewport> internalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100440 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700441 ASSERT_TRUE(internalViewport);
442 ASSERT_EQ(internalUniqueId, internalViewport->uniqueId);
443
444 // Check matching by type for external
445 std::optional<DisplayViewport> externalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100446 mFakePolicy->getDisplayViewportByType(ViewportType::EXTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700447 ASSERT_TRUE(externalViewport);
448 ASSERT_EQ(externalUniqueId, externalViewport->uniqueId);
449
450 // Check matching by uniqueId for virtual viewport #1
451 std::optional<DisplayViewport> virtualViewport1 =
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700452 mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId1);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700453 ASSERT_TRUE(virtualViewport1);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100454 ASSERT_EQ(ViewportType::VIRTUAL, virtualViewport1->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700455 ASSERT_EQ(virtualUniqueId1, virtualViewport1->uniqueId);
456 ASSERT_EQ(virtualDisplayId1, virtualViewport1->displayId);
457
458 // Check matching by uniqueId for virtual viewport #2
459 std::optional<DisplayViewport> virtualViewport2 =
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700460 mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId2);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700461 ASSERT_TRUE(virtualViewport2);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100462 ASSERT_EQ(ViewportType::VIRTUAL, virtualViewport2->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700463 ASSERT_EQ(virtualUniqueId2, virtualViewport2->uniqueId);
464 ASSERT_EQ(virtualDisplayId2, virtualViewport2->displayId);
465}
466
467
468/**
469 * We can have 2 viewports of the same kind. We can distinguish them by uniqueId, and confirm
470 * that lookup works by checking display id.
471 * Check that 2 viewports of each kind is possible, for all existing viewport types.
472 */
473TEST_F(InputReaderPolicyTest, Viewports_TwoOfSameType) {
474 const std::string uniqueId1 = "uniqueId1";
475 const std::string uniqueId2 = "uniqueId2";
Linnan Li13bf76a2024-05-05 19:18:02 +0800476 constexpr ui::LogicalDisplayId displayId1 = ui::LogicalDisplayId{2};
477 constexpr ui::LogicalDisplayId displayId2 = ui::LogicalDisplayId{3};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700478
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100479 std::vector<ViewportType> types = {ViewportType::INTERNAL, ViewportType::EXTERNAL,
480 ViewportType::VIRTUAL};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700481 for (const ViewportType& type : types) {
482 mFakePolicy->clearViewports();
483 // Add a viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000484 mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000485 /*isActive=*/true, uniqueId1, NO_PORT, type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700486 // Add another viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000487 mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000488 /*isActive=*/true, uniqueId2, NO_PORT, type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700489
490 // Check that correct display viewport was returned by comparing the display IDs.
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700491 std::optional<DisplayViewport> viewport1 =
492 mFakePolicy->getDisplayViewportByUniqueId(uniqueId1);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700493 ASSERT_TRUE(viewport1);
494 ASSERT_EQ(displayId1, viewport1->displayId);
495 ASSERT_EQ(type, viewport1->type);
496
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700497 std::optional<DisplayViewport> viewport2 =
498 mFakePolicy->getDisplayViewportByUniqueId(uniqueId2);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700499 ASSERT_TRUE(viewport2);
500 ASSERT_EQ(displayId2, viewport2->displayId);
501 ASSERT_EQ(type, viewport2->type);
502
503 // When there are multiple viewports of the same kind, and uniqueId is not specified
504 // in the call to getDisplayViewport, then that situation is not supported.
505 // The viewports can be stored in any order, so we cannot rely on the order, since that
506 // is just implementation detail.
507 // However, we can check that it still returns *a* viewport, we just cannot assert
508 // which one specifically is returned.
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700509 std::optional<DisplayViewport> someViewport = mFakePolicy->getDisplayViewportByType(type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700510 ASSERT_TRUE(someViewport);
511 }
512}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800513
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700514/**
Michael Wrightdde67b82020-10-27 16:09:22 +0000515 * When we have multiple internal displays make sure we always return the default display when
516 * querying by type.
517 */
518TEST_F(InputReaderPolicyTest, Viewports_ByTypeReturnsDefaultForInternal) {
519 const std::string uniqueId1 = "uniqueId1";
520 const std::string uniqueId2 = "uniqueId2";
Linnan Li13bf76a2024-05-05 19:18:02 +0800521 constexpr ui::LogicalDisplayId nonDefaultDisplayId = ui::LogicalDisplayId{2};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700522 ASSERT_NE(nonDefaultDisplayId, ui::LogicalDisplayId::DEFAULT)
523 << "Test display ID should not be ui::LogicalDisplayId::DEFAULT ";
Michael Wrightdde67b82020-10-27 16:09:22 +0000524
525 // Add the default display first and ensure it gets returned.
526 mFakePolicy->clearViewports();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700527 mFakePolicy->addDisplayViewport(ui::LogicalDisplayId::DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000528 ui::ROTATION_0, /*isActive=*/true, uniqueId1, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000529 ViewportType::INTERNAL);
530 mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000531 ui::ROTATION_0, /*isActive=*/true, uniqueId2, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000532 ViewportType::INTERNAL);
533
534 std::optional<DisplayViewport> viewport =
535 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
536 ASSERT_TRUE(viewport);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700537 ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, viewport->displayId);
Michael Wrightdde67b82020-10-27 16:09:22 +0000538 ASSERT_EQ(ViewportType::INTERNAL, viewport->type);
539
540 // Add the default display second to make sure order doesn't matter.
541 mFakePolicy->clearViewports();
542 mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000543 ui::ROTATION_0, /*isActive=*/true, uniqueId2, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000544 ViewportType::INTERNAL);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700545 mFakePolicy->addDisplayViewport(ui::LogicalDisplayId::DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000546 ui::ROTATION_0, /*isActive=*/true, uniqueId1, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000547 ViewportType::INTERNAL);
548
549 viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
550 ASSERT_TRUE(viewport);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700551 ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, viewport->displayId);
Michael Wrightdde67b82020-10-27 16:09:22 +0000552 ASSERT_EQ(ViewportType::INTERNAL, viewport->type);
553}
554
555/**
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700556 * Check getDisplayViewportByPort
557 */
558TEST_F(InputReaderPolicyTest, Viewports_GetByPort) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100559 constexpr ViewportType type = ViewportType::EXTERNAL;
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700560 const std::string uniqueId1 = "uniqueId1";
561 const std::string uniqueId2 = "uniqueId2";
Linnan Li13bf76a2024-05-05 19:18:02 +0800562 constexpr ui::LogicalDisplayId displayId1 = ui::LogicalDisplayId{1};
563 constexpr ui::LogicalDisplayId displayId2 = ui::LogicalDisplayId{2};
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700564 const uint8_t hdmi1 = 0;
565 const uint8_t hdmi2 = 1;
566 const uint8_t hdmi3 = 2;
567
568 mFakePolicy->clearViewports();
569 // Add a viewport that's associated with some display port that's not of interest.
Michael Wrighta9cf4192022-12-01 23:46:39 +0000570 mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000571 /*isActive=*/true, uniqueId1, hdmi3, type);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700572 // Add another viewport, connected to HDMI1 port
Michael Wrighta9cf4192022-12-01 23:46:39 +0000573 mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000574 /*isActive=*/true, uniqueId2, hdmi1, type);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700575
576 // Check that correct display viewport was returned by comparing the display ports.
577 std::optional<DisplayViewport> hdmi1Viewport = mFakePolicy->getDisplayViewportByPort(hdmi1);
578 ASSERT_TRUE(hdmi1Viewport);
579 ASSERT_EQ(displayId2, hdmi1Viewport->displayId);
580 ASSERT_EQ(uniqueId2, hdmi1Viewport->uniqueId);
581
582 // Check that we can still get the same viewport using the uniqueId
583 hdmi1Viewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId2);
584 ASSERT_TRUE(hdmi1Viewport);
585 ASSERT_EQ(displayId2, hdmi1Viewport->displayId);
586 ASSERT_EQ(uniqueId2, hdmi1Viewport->uniqueId);
587 ASSERT_EQ(type, hdmi1Viewport->type);
588
589 // Check that we cannot find a port with "HDMI2", because we never added one
590 std::optional<DisplayViewport> hdmi2Viewport = mFakePolicy->getDisplayViewportByPort(hdmi2);
591 ASSERT_FALSE(hdmi2Viewport);
592}
593
Michael Wrightd02c5b62014-02-10 15:10:22 -0800594// --- InputReaderTest ---
595
596class InputReaderTest : public testing::Test {
597protected:
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700598 std::unique_ptr<TestInputListener> mFakeListener;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800599 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou3bc7e092019-07-24 17:43:30 -0700600 std::shared_ptr<FakeEventHub> mFakeEventHub;
Prabir Pradhan28efc192019-11-05 01:10:04 +0000601 std::unique_ptr<InstrumentedInputReader> mReader;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800602
Chris Yea52ade12020-08-27 16:49:20 -0700603 void SetUp() override {
Siarhei Vishniakou3bc7e092019-07-24 17:43:30 -0700604 mFakeEventHub = std::make_unique<FakeEventHub>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700605 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700606 mFakeListener = std::make_unique<TestInputListener>();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800607
Prabir Pradhan28efc192019-11-05 01:10:04 +0000608 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700609 *mFakeListener);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800610 }
611
Chris Yea52ade12020-08-27 16:49:20 -0700612 void TearDown() override {
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700613 mFakeListener.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800614 mFakePolicy.clear();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800615 }
616
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700617 void addDevice(int32_t eventHubId, const std::string& name,
618 ftl::Flags<InputDeviceClass> classes, const PropertyMap* configuration) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800619 mFakeEventHub->addDevice(eventHubId, name, classes);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800620
621 if (configuration) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800622 mFakeEventHub->addConfigurationMap(eventHubId, configuration);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800623 }
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000624 mReader->loopOnce();
625 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700626 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Prabir Pradhane3da4bb2023-04-05 23:51:23 +0000627 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyInputDevicesChangedWasCalled());
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700628 ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800629 }
630
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800631 void disableDevice(int32_t deviceId) {
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700632 mFakePolicy->addDisabledDevice(deviceId);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000633 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::ENABLED_STATE);
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700634 }
635
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800636 void enableDevice(int32_t deviceId) {
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700637 mFakePolicy->removeDisabledDevice(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. Lewisa7b82e12020-02-12 15:40:45 -0800641 FakeInputMapper& addDeviceWithFakeInputMapper(int32_t deviceId, int32_t eventHubId,
Chris Ye1b0c7342020-07-28 21:57:03 -0700642 const std::string& name,
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700643 ftl::Flags<InputDeviceClass> classes,
644 uint32_t sources,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800645 const PropertyMap* configuration) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800646 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, name);
Arpit Singh8e6fb252023-04-06 11:49:17 +0000647 FakeInputMapper& mapper =
648 device->addMapper<FakeInputMapper>(eventHubId,
649 mFakePolicy->getReaderConfiguration(), sources);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -0800650 mReader->pushNextDevice(device);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800651 addDevice(eventHubId, name, classes, configuration);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800652 return mapper;
653 }
654};
655
Chris Ye98d3f532020-10-01 21:48:59 -0700656TEST_F(InputReaderTest, PolicyGetInputDevices) {
657 ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard", InputDeviceClass::KEYBOARD, nullptr));
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700658 ASSERT_NO_FATAL_FAILURE(addDevice(2, "ignored", ftl::Flags<InputDeviceClass>(0),
Chris Ye98d3f532020-10-01 21:48:59 -0700659 nullptr)); // no classes so device will be ignored
Michael Wrightd02c5b62014-02-10 15:10:22 -0800660
661 // Should also have received a notification describing the new input devices.
Chris Ye98d3f532020-10-01 21:48:59 -0700662 const std::vector<InputDeviceInfo>& inputDevices = mFakePolicy->getInputDevices();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800663 ASSERT_EQ(1U, inputDevices.size());
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800664 ASSERT_EQ(END_RESERVED_ID + 1, inputDevices[0].getId());
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100665 ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800666 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, inputDevices[0].getKeyboardType());
667 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, inputDevices[0].getSources());
Siarhei Vishniakou1983a712021-06-04 19:27:09 +0000668 ASSERT_EQ(0U, inputDevices[0].getMotionRanges().size());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800669}
670
Vaibhav Devmurari5fc7d852023-03-17 18:43:33 +0000671TEST_F(InputReaderTest, InputDeviceRecreatedOnSysfsNodeChanged) {
672 ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard", InputDeviceClass::KEYBOARD, nullptr));
673 mFakeEventHub->setSysfsRootPath(1, "xyz");
674
675 // Should also have received a notification describing the new input device.
676 ASSERT_EQ(1U, mFakePolicy->getInputDevices().size());
677 InputDeviceInfo inputDevice = mFakePolicy->getInputDevices()[0];
678 ASSERT_EQ(0U, inputDevice.getLights().size());
679
680 RawLightInfo infoMonolight = {.id = 123,
681 .name = "mono_keyboard_backlight",
682 .maxBrightness = 255,
683 .flags = InputLightClass::BRIGHTNESS,
684 .path = ""};
685 mFakeEventHub->addRawLightInfo(/*rawId=*/123, std::move(infoMonolight));
686 mReader->sysfsNodeChanged("xyz");
687 mReader->loopOnce();
688
689 // Should also have received a notification describing the new recreated input device.
690 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
691 inputDevice = mFakePolicy->getInputDevices()[0];
692 ASSERT_EQ(1U, inputDevice.getLights().size());
693}
694
Chris Yee7310032020-09-22 15:36:28 -0700695TEST_F(InputReaderTest, GetMergedInputDevices) {
696 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
697 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
698 // Add two subdevices to device
699 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
700 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000701 device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
702 AINPUT_SOURCE_KEYBOARD);
703 device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
704 AINPUT_SOURCE_KEYBOARD);
Chris Yee7310032020-09-22 15:36:28 -0700705
706 // Push same device instance for next device to be added, so they'll have same identifier.
707 mReader->pushNextDevice(device);
708 mReader->pushNextDevice(device);
709 ASSERT_NO_FATAL_FAILURE(
710 addDevice(eventHubIds[0], "fake1", InputDeviceClass::KEYBOARD, nullptr));
711 ASSERT_NO_FATAL_FAILURE(
712 addDevice(eventHubIds[1], "fake2", InputDeviceClass::KEYBOARD, nullptr));
713
714 // Two devices will be merged to one input device as they have same identifier
Siarhei Vishniakou1983a712021-06-04 19:27:09 +0000715 ASSERT_EQ(1U, mFakePolicy->getInputDevices().size());
Chris Yee7310032020-09-22 15:36:28 -0700716}
717
Chris Yee14523a2020-12-19 13:46:00 -0800718TEST_F(InputReaderTest, GetMergedInputDevicesEnabled) {
719 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
720 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
721 // Add two subdevices to device
722 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
723 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000724 device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
725 AINPUT_SOURCE_KEYBOARD);
726 device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
727 AINPUT_SOURCE_KEYBOARD);
Chris Yee14523a2020-12-19 13:46:00 -0800728
729 // Push same device instance for next device to be added, so they'll have same identifier.
730 mReader->pushNextDevice(device);
731 mReader->pushNextDevice(device);
732 // Sensor device is initially disabled
733 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1",
734 InputDeviceClass::KEYBOARD | InputDeviceClass::SENSOR,
735 nullptr));
736 // Device is disabled because the only sub device is a sensor device and disabled initially.
737 ASSERT_FALSE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
738 ASSERT_FALSE(device->isEnabled());
739 ASSERT_NO_FATAL_FAILURE(
740 addDevice(eventHubIds[1], "fake2", InputDeviceClass::KEYBOARD, nullptr));
741 // The merged device is enabled if any sub device is enabled
742 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
743 ASSERT_TRUE(device->isEnabled());
744}
745
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700746TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800747 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700748 constexpr ftl::Flags<InputDeviceClass> deviceClass(InputDeviceClass::KEYBOARD);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800749 constexpr int32_t eventHubId = 1;
750 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700751 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000752 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
753 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -0800754 mReader->pushNextDevice(device);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800755 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700756
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700757 NotifyDeviceResetArgs resetArgs;
758 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700759 ASSERT_EQ(deviceId, resetArgs.deviceId);
760
761 ASSERT_EQ(device->isEnabled(), true);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800762 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000763 mReader->loopOnce();
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700764
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700765 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700766 ASSERT_EQ(deviceId, resetArgs.deviceId);
767 ASSERT_EQ(device->isEnabled(), false);
768
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800769 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000770 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700771 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700772 ASSERT_EQ(device->isEnabled(), false);
773
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800774 enableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000775 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700776 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700777 ASSERT_EQ(deviceId, resetArgs.deviceId);
778 ASSERT_EQ(device->isEnabled(), true);
779}
780
Michael Wrightd02c5b62014-02-10 15:10:22 -0800781TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800782 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700783 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800784 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800785 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800786 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800787 AINPUT_SOURCE_KEYBOARD, nullptr);
788 mapper.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800789
790 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(0,
791 AINPUT_SOURCE_ANY, AKEYCODE_A))
792 << "Should return unknown when the device id is >= 0 but unknown.";
793
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800794 ASSERT_EQ(AKEY_STATE_UNKNOWN,
795 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
796 << "Should return unknown when the device id is valid but the sources are not "
797 "supported by the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800798
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800799 ASSERT_EQ(AKEY_STATE_DOWN,
800 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
801 AKEYCODE_A))
802 << "Should return value provided by mapper when device id is valid and the device "
803 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800804
805 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(-1,
806 AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
807 << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
808
809 ASSERT_EQ(AKEY_STATE_DOWN, mReader->getKeyCodeState(-1,
810 AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
811 << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
812}
813
Philip Junker4af3b3d2021-12-14 10:36:55 +0100814TEST_F(InputReaderTest, GetKeyCodeForKeyLocation_ForwardsRequestsToMappers) {
815 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
816 constexpr int32_t eventHubId = 1;
817 FakeInputMapper& mapper = addDeviceWithFakeInputMapper(deviceId, eventHubId, "keyboard",
818 InputDeviceClass::KEYBOARD,
819 AINPUT_SOURCE_KEYBOARD, nullptr);
820 mapper.addKeyCodeMapping(AKEYCODE_Y, AKEYCODE_Z);
821
822 ASSERT_EQ(AKEYCODE_UNKNOWN, mReader->getKeyCodeForKeyLocation(0, AKEYCODE_Y))
823 << "Should return unknown when the device with the specified id is not found.";
824
825 ASSERT_EQ(AKEYCODE_Z, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_Y))
826 << "Should return correct mapping when device id is valid and mapping exists.";
827
828 ASSERT_EQ(AKEYCODE_A, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_A))
829 << "Should return the location key code when device id is valid and there's no "
830 "mapping.";
831}
832
833TEST_F(InputReaderTest, GetKeyCodeForKeyLocation_NoKeyboardMapper) {
834 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
835 constexpr int32_t eventHubId = 1;
836 FakeInputMapper& mapper = addDeviceWithFakeInputMapper(deviceId, eventHubId, "joystick",
837 InputDeviceClass::JOYSTICK,
838 AINPUT_SOURCE_GAMEPAD, nullptr);
839 mapper.addKeyCodeMapping(AKEYCODE_Y, AKEYCODE_Z);
840
841 ASSERT_EQ(AKEYCODE_UNKNOWN, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_Y))
842 << "Should return unknown when the device id is valid but there is no keyboard mapper";
843}
844
Michael Wrightd02c5b62014-02-10 15:10:22 -0800845TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800846 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700847 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800848 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800849 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800850 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800851 AINPUT_SOURCE_KEYBOARD, nullptr);
852 mapper.setScanCodeState(KEY_A, AKEY_STATE_DOWN);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800853
854 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(0,
855 AINPUT_SOURCE_ANY, KEY_A))
856 << "Should return unknown when the device id is >= 0 but unknown.";
857
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800858 ASSERT_EQ(AKEY_STATE_UNKNOWN,
859 mReader->getScanCodeState(deviceId, AINPUT_SOURCE_TRACKBALL, KEY_A))
860 << "Should return unknown when the device id is valid but the sources are not "
861 "supported by the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800862
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800863 ASSERT_EQ(AKEY_STATE_DOWN,
864 mReader->getScanCodeState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
865 KEY_A))
866 << "Should return value provided by mapper when device id is valid and the device "
867 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800868
869 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(-1,
870 AINPUT_SOURCE_TRACKBALL, KEY_A))
871 << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
872
873 ASSERT_EQ(AKEY_STATE_DOWN, mReader->getScanCodeState(-1,
874 AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, KEY_A))
875 << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
876}
877
878TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800879 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700880 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800881 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800882 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800883 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800884 AINPUT_SOURCE_KEYBOARD, nullptr);
885 mapper.setSwitchState(SW_LID, AKEY_STATE_DOWN);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800886
887 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(0,
888 AINPUT_SOURCE_ANY, SW_LID))
889 << "Should return unknown when the device id is >= 0 but unknown.";
890
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800891 ASSERT_EQ(AKEY_STATE_UNKNOWN,
892 mReader->getSwitchState(deviceId, AINPUT_SOURCE_TRACKBALL, SW_LID))
893 << "Should return unknown when the device id is valid but the sources are not "
894 "supported by the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800895
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800896 ASSERT_EQ(AKEY_STATE_DOWN,
897 mReader->getSwitchState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
898 SW_LID))
899 << "Should return value provided by mapper when device id is valid and the device "
900 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800901
902 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(-1,
903 AINPUT_SOURCE_TRACKBALL, SW_LID))
904 << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
905
906 ASSERT_EQ(AKEY_STATE_DOWN, mReader->getSwitchState(-1,
907 AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, SW_LID))
908 << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
909}
910
911TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800912 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700913 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800914 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800915 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800916 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800917 AINPUT_SOURCE_KEYBOARD, nullptr);
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100918
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800919 mapper.addSupportedKeyCode(AKEYCODE_A);
920 mapper.addSupportedKeyCode(AKEYCODE_B);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800921
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700922 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800923 uint8_t flags[4] = { 0, 0, 0, 1 };
924
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700925 ASSERT_FALSE(mReader->hasKeys(0, AINPUT_SOURCE_ANY, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800926 << "Should return false when device id is >= 0 but unknown.";
927 ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
928
929 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700930 ASSERT_FALSE(mReader->hasKeys(deviceId, AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800931 << "Should return false when device id is valid but the sources are not supported by "
932 "the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800933 ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
934
935 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700936 ASSERT_TRUE(mReader->hasKeys(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800937 keyCodes, flags))
938 << "Should return value provided by mapper when device id is valid and the device "
939 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800940 ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
941
942 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700943 ASSERT_FALSE(mReader->hasKeys(-1, AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
944 << "Should return false when the device id is < 0 but the sources are not supported by "
945 "any device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800946 ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
947
948 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700949 ASSERT_TRUE(
950 mReader->hasKeys(-1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
951 << "Should return value provided by mapper when device id is < 0 and one of the "
952 "devices supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800953 ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
954}
955
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000956TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800957 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700958 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000959 constexpr nsecs_t when = 0;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800960 constexpr int32_t eventHubId = 1;
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000961 constexpr nsecs_t readTime = 2;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800962 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800963 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800964 AINPUT_SOURCE_KEYBOARD, nullptr);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800965
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000966 mFakeEventHub->enqueueEvent(when, readTime, eventHubId, EV_KEY, KEY_A, 1);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000967 mReader->loopOnce();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800968 ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty());
969
970 RawEvent event;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800971 ASSERT_NO_FATAL_FAILURE(mapper.assertProcessWasCalled(&event));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000972 ASSERT_EQ(when, event.when);
973 ASSERT_EQ(readTime, event.readTime);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800974 ASSERT_EQ(eventHubId, event.deviceId);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800975 ASSERT_EQ(EV_KEY, event.type);
976 ASSERT_EQ(KEY_A, event.code);
977 ASSERT_EQ(1, event.value);
978}
979
Garfield Tan1c7bc862020-01-28 13:24:04 -0800980TEST_F(InputReaderTest, DeviceReset_RandomId) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800981 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700982 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800983 constexpr int32_t eventHubId = 1;
984 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
Prabir Pradhan42611e02018-11-27 14:04:02 -0800985 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000986 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
987 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -0800988 mReader->pushNextDevice(device);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800989 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Prabir Pradhan42611e02018-11-27 14:04:02 -0800990
991 NotifyDeviceResetArgs resetArgs;
992 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800993 int32_t prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -0800994
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800995 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000996 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700997 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tan1c7bc862020-01-28 13:24:04 -0800998 ASSERT_NE(prevId, resetArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800999 prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001000
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001001 enableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001002 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -07001003 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tan1c7bc862020-01-28 13:24:04 -08001004 ASSERT_NE(prevId, resetArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001005 prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001006
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001007 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001008 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -07001009 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tan1c7bc862020-01-28 13:24:04 -08001010 ASSERT_NE(prevId, resetArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001011 prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001012}
1013
Garfield Tan1c7bc862020-01-28 13:24:04 -08001014TEST_F(InputReaderTest, DeviceReset_GenerateIdWithInputReaderSource) {
1015 constexpr int32_t deviceId = 1;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001016 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Garfield Tan1c7bc862020-01-28 13:24:04 -08001017 constexpr int32_t eventHubId = 1;
1018 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
1019 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +00001020 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
1021 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001022 mReader->pushNextDevice(device);
Garfield Tan1c7bc862020-01-28 13:24:04 -08001023 ASSERT_NO_FATAL_FAILURE(addDevice(deviceId, "fake", deviceClass, nullptr));
1024
1025 NotifyDeviceResetArgs resetArgs;
1026 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1027 ASSERT_EQ(IdGenerator::Source::INPUT_READER, IdGenerator::getSource(resetArgs.id));
1028}
1029
Arthur Hungc23540e2018-11-29 20:42:11 +08001030TEST_F(InputReaderTest, Device_CanDispatchToDisplay) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001031 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001032 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001033 constexpr int32_t eventHubId = 1;
Arthur Hungc23540e2018-11-29 20:42:11 +08001034 const char* DEVICE_LOCATION = "USB1";
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001035 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
1036 FakeInputMapper& mapper =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001037 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
1038 AINPUT_SOURCE_TOUCHSCREEN);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001039 mReader->pushNextDevice(device);
Arthur Hungc23540e2018-11-29 20:42:11 +08001040
1041 const uint8_t hdmi1 = 1;
1042
1043 // Associated touch screen with second display.
1044 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
1045
1046 // Add default and second display.
Prabir Pradhan28efc192019-11-05 01:10:04 +00001047 mFakePolicy->clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00001048 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00001049 /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL);
Arthur Hungc23540e2018-11-29 20:42:11 +08001050 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +00001051 ui::ROTATION_0, /*isActive=*/true, "local:1", hdmi1,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01001052 ViewportType::EXTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001053 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::DISPLAY_INFO);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001054 mReader->loopOnce();
Prabir Pradhan28efc192019-11-05 01:10:04 +00001055
1056 // Add the device, and make sure all of the callbacks are triggered.
1057 // The device is added after the input port associations are processed since
1058 // we do not yet support dynamic device-to-display associations.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001059 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Prabir Pradhan28efc192019-11-05 01:10:04 +00001060 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001061 ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
Arthur Hungc23540e2018-11-29 20:42:11 +08001062
Arthur Hung2c9a3342019-07-23 14:18:59 +08001063 // Device should only dispatch to the specified display.
Arthur Hungc23540e2018-11-29 20:42:11 +08001064 ASSERT_EQ(deviceId, device->getId());
1065 ASSERT_FALSE(mReader->canDispatchToDisplay(deviceId, DISPLAY_ID));
1066 ASSERT_TRUE(mReader->canDispatchToDisplay(deviceId, SECONDARY_DISPLAY_ID));
Arthur Hung2c9a3342019-07-23 14:18:59 +08001067
1068 // Can't dispatch event from a disabled device.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001069 disableDevice(deviceId);
Prabir Pradhan28efc192019-11-05 01:10:04 +00001070 mReader->loopOnce();
Arthur Hung2c9a3342019-07-23 14:18:59 +08001071 ASSERT_FALSE(mReader->canDispatchToDisplay(deviceId, SECONDARY_DISPLAY_ID));
Arthur Hungc23540e2018-11-29 20:42:11 +08001072}
1073
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001074TEST_F(InputReaderTest, WhenEnabledChanges_AllSubdevicesAreUpdated) {
1075 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001076 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001077 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
1078 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
1079 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +00001080 device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
1081 AINPUT_SOURCE_KEYBOARD);
1082 device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
1083 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001084 mReader->pushNextDevice(device);
1085 mReader->pushNextDevice(device);
1086 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1", deviceClass, nullptr));
1087 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[1], "fake2", deviceClass, nullptr));
1088
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001089 NotifyDeviceResetArgs resetArgs;
1090 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1091 ASSERT_EQ(deviceId, resetArgs.deviceId);
1092 ASSERT_TRUE(device->isEnabled());
1093 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
1094 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
1095
1096 disableDevice(deviceId);
1097 mReader->loopOnce();
1098
1099 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1100 ASSERT_EQ(deviceId, resetArgs.deviceId);
1101 ASSERT_FALSE(device->isEnabled());
1102 ASSERT_FALSE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
1103 ASSERT_FALSE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
1104
1105 enableDevice(deviceId);
1106 mReader->loopOnce();
1107
1108 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1109 ASSERT_EQ(deviceId, resetArgs.deviceId);
1110 ASSERT_TRUE(device->isEnabled());
1111 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
1112 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
1113}
1114
1115TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToSubdeviceMappers) {
1116 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001117 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001118 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
1119 // Add two subdevices to device
1120 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
1121 FakeInputMapper& mapperDevice1 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001122 device->addMapper<FakeInputMapper>(eventHubIds[0],
1123 mFakePolicy->getReaderConfiguration(),
1124 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001125 FakeInputMapper& mapperDevice2 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001126 device->addMapper<FakeInputMapper>(eventHubIds[1],
1127 mFakePolicy->getReaderConfiguration(),
1128 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001129 mReader->pushNextDevice(device);
1130 mReader->pushNextDevice(device);
1131 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1", deviceClass, nullptr));
1132 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[1], "fake2", deviceClass, nullptr));
1133
1134 mapperDevice1.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
1135 mapperDevice2.setKeyCodeState(AKEYCODE_B, AKEY_STATE_DOWN);
1136
1137 ASSERT_EQ(AKEY_STATE_DOWN,
1138 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_A));
1139 ASSERT_EQ(AKEY_STATE_DOWN,
1140 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_B));
1141 ASSERT_EQ(AKEY_STATE_UNKNOWN,
1142 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_C));
1143}
1144
Prabir Pradhan7e186182020-11-10 13:56:45 -08001145TEST_F(InputReaderTest, ChangingPointerCaptureNotifiesInputListener) {
1146 NotifyPointerCaptureChangedArgs args;
1147
Hiroki Sato25040232024-02-22 17:21:22 +09001148 auto request = mFakePolicy->setPointerCapture(/*window=*/sp<BBinder>::make());
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001149 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE);
Prabir Pradhan7e186182020-11-10 13:56:45 -08001150 mReader->loopOnce();
1151 mFakeListener->assertNotifyCaptureWasCalled(&args);
Hiroki Sato25040232024-02-22 17:21:22 +09001152 ASSERT_TRUE(args.request.isEnable()) << "Pointer Capture should be enabled.";
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001153 ASSERT_EQ(args.request, request) << "Pointer Capture sequence number should match.";
Prabir Pradhan7e186182020-11-10 13:56:45 -08001154
Hiroki Sato25040232024-02-22 17:21:22 +09001155 mFakePolicy->setPointerCapture(/*window=*/nullptr);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001156 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE);
Prabir Pradhan7e186182020-11-10 13:56:45 -08001157 mReader->loopOnce();
1158 mFakeListener->assertNotifyCaptureWasCalled(&args);
Hiroki Sato25040232024-02-22 17:21:22 +09001159 ASSERT_FALSE(args.request.isEnable()) << "Pointer Capture should be disabled.";
Prabir Pradhan7e186182020-11-10 13:56:45 -08001160
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001161 // Verify that the Pointer Capture state is not updated when the configuration value
Prabir Pradhan7e186182020-11-10 13:56:45 -08001162 // does not change.
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001163 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE);
Prabir Pradhan7e186182020-11-10 13:56:45 -08001164 mReader->loopOnce();
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001165 mFakeListener->assertNotifyCaptureWasNotCalled();
Prabir Pradhan7e186182020-11-10 13:56:45 -08001166}
1167
Prabir Pradhan018faea2024-05-08 21:52:54 +00001168TEST_F(InputReaderTest, GetLastUsedInputDeviceId) {
1169 constexpr int32_t FIRST_DEVICE_ID = END_RESERVED_ID + 1000;
1170 constexpr int32_t SECOND_DEVICE_ID = FIRST_DEVICE_ID + 1;
1171 FakeInputMapper& firstMapper =
1172 addDeviceWithFakeInputMapper(FIRST_DEVICE_ID, FIRST_DEVICE_ID, "first",
1173 InputDeviceClass::KEYBOARD, AINPUT_SOURCE_KEYBOARD,
1174 /*configuration=*/nullptr);
1175 FakeInputMapper& secondMapper =
1176 addDeviceWithFakeInputMapper(SECOND_DEVICE_ID, SECOND_DEVICE_ID, "second",
1177 InputDeviceClass::TOUCH_MT, AINPUT_SOURCE_STYLUS,
1178 /*configuration=*/nullptr);
1179
1180 ASSERT_EQ(ReservedInputDeviceId::INVALID_INPUT_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1181
1182 // Start a new key gesture from the first device
1183 firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
1184 .deviceId(FIRST_DEVICE_ID)
1185 .build()});
1186 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
1187 mReader->loopOnce();
1188 ASSERT_EQ(firstMapper.getDeviceId(), mReader->getLastUsedInputDeviceId());
1189
1190 // Start a new touch gesture from the second device
1191 secondMapper.setProcessResult(
1192 {MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
1193 .deviceId(SECOND_DEVICE_ID)
1194 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER))
1195 .build()});
1196 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
1197 mReader->loopOnce();
1198 ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1199
1200 // Releasing the key is not a new gesture, so it does not update the last used device
1201 firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
1202 .deviceId(FIRST_DEVICE_ID)
1203 .build()});
1204 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
1205 mReader->loopOnce();
1206 ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1207
1208 // But pressing a new key does start a new gesture
1209 firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
1210 .deviceId(FIRST_DEVICE_ID)
1211 .build()});
1212 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
1213 mReader->loopOnce();
1214 ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1215
1216 // Moving or ending a touch gesture does not update the last used device
1217 secondMapper.setProcessResult(
1218 {MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
1219 .deviceId(SECOND_DEVICE_ID)
1220 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
1221 .build()});
1222 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
1223 mReader->loopOnce();
1224 ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1225 secondMapper.setProcessResult({MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
1226 .deviceId(SECOND_DEVICE_ID)
1227 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
1228 .build()});
1229 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
1230 mReader->loopOnce();
1231 ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1232
1233 // Starting a new hover gesture updates the last used device
1234 secondMapper.setProcessResult(
1235 {MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1236 .deviceId(SECOND_DEVICE_ID)
1237 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
1238 .build()});
1239 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
1240 mReader->loopOnce();
1241 ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1242}
1243
Chris Ye87143712020-11-10 05:05:58 +00001244class FakeVibratorInputMapper : public FakeInputMapper {
1245public:
Arpit Singh8e6fb252023-04-06 11:49:17 +00001246 FakeVibratorInputMapper(InputDeviceContext& deviceContext,
1247 const InputReaderConfiguration& readerConfig, uint32_t sources)
1248 : FakeInputMapper(deviceContext, readerConfig, sources) {}
Chris Ye87143712020-11-10 05:05:58 +00001249
1250 std::vector<int32_t> getVibratorIds() override { return getDeviceContext().getVibratorIds(); }
1251};
1252
1253TEST_F(InputReaderTest, VibratorGetVibratorIds) {
1254 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001255 ftl::Flags<InputDeviceClass> deviceClass =
1256 InputDeviceClass::KEYBOARD | InputDeviceClass::VIBRATOR;
Chris Ye87143712020-11-10 05:05:58 +00001257 constexpr int32_t eventHubId = 1;
1258 const char* DEVICE_LOCATION = "BLUETOOTH";
1259 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
1260 FakeVibratorInputMapper& mapper =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001261 device->addMapper<FakeVibratorInputMapper>(eventHubId,
1262 mFakePolicy->getReaderConfiguration(),
1263 AINPUT_SOURCE_KEYBOARD);
Chris Ye87143712020-11-10 05:05:58 +00001264 mReader->pushNextDevice(device);
1265
1266 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1267 ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
1268
1269 ASSERT_EQ(mapper.getVibratorIds().size(), 2U);
1270 ASSERT_EQ(mReader->getVibratorIds(deviceId).size(), 2U);
1271}
1272
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001273// --- FakePeripheralController ---
Kim Low03ea0352020-11-06 12:45:07 -08001274
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001275class FakePeripheralController : public PeripheralControllerInterface {
Chris Yee2b1e5c2021-03-10 22:45:12 -08001276public:
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001277 FakePeripheralController(InputDeviceContext& deviceContext) : mDeviceContext(deviceContext) {}
Chris Yee2b1e5c2021-03-10 22:45:12 -08001278
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001279 ~FakePeripheralController() override {}
Chris Yee2b1e5c2021-03-10 22:45:12 -08001280
Andy Chenf9f1a022022-08-29 20:07:10 -04001281 int32_t getEventHubId() const { return getDeviceContext().getEventHubId(); }
1282
Chris Yee2b1e5c2021-03-10 22:45:12 -08001283 void populateDeviceInfo(InputDeviceInfo* deviceInfo) override {}
1284
1285 void dump(std::string& dump) override {}
1286
1287 std::optional<int32_t> getBatteryCapacity(int32_t batteryId) override {
1288 return getDeviceContext().getBatteryCapacity(batteryId);
Kim Low03ea0352020-11-06 12:45:07 -08001289 }
1290
Chris Yee2b1e5c2021-03-10 22:45:12 -08001291 std::optional<int32_t> getBatteryStatus(int32_t batteryId) override {
1292 return getDeviceContext().getBatteryStatus(batteryId);
Kim Low03ea0352020-11-06 12:45:07 -08001293 }
Chris Ye3fdbfef2021-01-06 18:45:18 -08001294
1295 bool setLightColor(int32_t lightId, int32_t color) override {
1296 getDeviceContext().setLightBrightness(lightId, color >> 24);
1297 return true;
1298 }
1299
1300 std::optional<int32_t> getLightColor(int32_t lightId) override {
1301 std::optional<int32_t> result = getDeviceContext().getLightBrightness(lightId);
1302 if (!result.has_value()) {
1303 return std::nullopt;
1304 }
1305 return result.value() << 24;
1306 }
Chris Yee2b1e5c2021-03-10 22:45:12 -08001307
1308 bool setLightPlayerId(int32_t lightId, int32_t playerId) override { return true; }
1309
1310 std::optional<int32_t> getLightPlayerId(int32_t lightId) override { return std::nullopt; }
1311
1312private:
1313 InputDeviceContext& mDeviceContext;
1314 inline int32_t getDeviceId() { return mDeviceContext.getId(); }
1315 inline InputDeviceContext& getDeviceContext() { return mDeviceContext; }
Andy Chenf9f1a022022-08-29 20:07:10 -04001316 inline InputDeviceContext& getDeviceContext() const { return mDeviceContext; }
Chris Ye3fdbfef2021-01-06 18:45:18 -08001317};
1318
Chris Yee2b1e5c2021-03-10 22:45:12 -08001319TEST_F(InputReaderTest, BatteryGetCapacity) {
1320 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001321 ftl::Flags<InputDeviceClass> deviceClass =
1322 InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
Chris Yee2b1e5c2021-03-10 22:45:12 -08001323 constexpr int32_t eventHubId = 1;
1324 const char* DEVICE_LOCATION = "BLUETOOTH";
1325 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001326 FakePeripheralController& controller =
1327 device->addController<FakePeripheralController>(eventHubId);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001328 mReader->pushNextDevice(device);
1329
1330 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1331
Harry Cuttsa5b71292022-11-28 12:56:17 +00001332 ASSERT_EQ(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY),
1333 FakeEventHub::BATTERY_CAPACITY);
1334 ASSERT_EQ(mReader->getBatteryCapacity(deviceId), FakeEventHub::BATTERY_CAPACITY);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001335}
1336
1337TEST_F(InputReaderTest, BatteryGetStatus) {
1338 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001339 ftl::Flags<InputDeviceClass> deviceClass =
1340 InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
Chris Yee2b1e5c2021-03-10 22:45:12 -08001341 constexpr int32_t eventHubId = 1;
1342 const char* DEVICE_LOCATION = "BLUETOOTH";
1343 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001344 FakePeripheralController& controller =
1345 device->addController<FakePeripheralController>(eventHubId);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001346 mReader->pushNextDevice(device);
1347
1348 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1349
Harry Cuttsa5b71292022-11-28 12:56:17 +00001350 ASSERT_EQ(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY),
1351 FakeEventHub::BATTERY_STATUS);
1352 ASSERT_EQ(mReader->getBatteryStatus(deviceId), FakeEventHub::BATTERY_STATUS);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001353}
1354
Prabir Pradhane287ecd2022-09-07 21:18:05 +00001355TEST_F(InputReaderTest, BatteryGetDevicePath) {
1356 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
1357 ftl::Flags<InputDeviceClass> deviceClass =
1358 InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
1359 constexpr int32_t eventHubId = 1;
1360 const char* DEVICE_LOCATION = "BLUETOOTH";
1361 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
1362 device->addController<FakePeripheralController>(eventHubId);
1363 mReader->pushNextDevice(device);
1364
1365 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1366
Harry Cuttsa5b71292022-11-28 12:56:17 +00001367 ASSERT_EQ(mReader->getBatteryDevicePath(deviceId), FakeEventHub::BATTERY_DEVPATH);
Prabir Pradhane287ecd2022-09-07 21:18:05 +00001368}
1369
Chris Ye3fdbfef2021-01-06 18:45:18 -08001370TEST_F(InputReaderTest, LightGetColor) {
1371 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001372 ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::LIGHT;
Chris Ye3fdbfef2021-01-06 18:45:18 -08001373 constexpr int32_t eventHubId = 1;
1374 const char* DEVICE_LOCATION = "BLUETOOTH";
1375 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001376 FakePeripheralController& controller =
1377 device->addController<FakePeripheralController>(eventHubId);
Chris Ye3fdbfef2021-01-06 18:45:18 -08001378 mReader->pushNextDevice(device);
1379 RawLightInfo info = {.id = 1,
1380 .name = "Mono",
1381 .maxBrightness = 255,
1382 .flags = InputLightClass::BRIGHTNESS,
1383 .path = ""};
Harry Cutts33476232023-01-30 19:57:29 +00001384 mFakeEventHub->addRawLightInfo(/*rawId=*/1, std::move(info));
1385 mFakeEventHub->fakeLightBrightness(/*rawId=*/1, 0x55);
Chris Ye3fdbfef2021-01-06 18:45:18 -08001386
1387 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Chris Ye3fdbfef2021-01-06 18:45:18 -08001388
Harry Cutts33476232023-01-30 19:57:29 +00001389 ASSERT_TRUE(controller.setLightColor(/*lightId=*/1, LIGHT_BRIGHTNESS));
1390 ASSERT_EQ(controller.getLightColor(/*lightId=*/1), LIGHT_BRIGHTNESS);
1391 ASSERT_TRUE(mReader->setLightColor(deviceId, /*lightId=*/1, LIGHT_BRIGHTNESS));
1392 ASSERT_EQ(mReader->getLightColor(deviceId, /*lightId=*/1), LIGHT_BRIGHTNESS);
Chris Ye3fdbfef2021-01-06 18:45:18 -08001393}
1394
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001395// --- InputReaderIntegrationTest ---
1396
1397// These tests create and interact with the InputReader only through its interface.
1398// The InputReader is started during SetUp(), which starts its processing in its own
1399// thread. The tests use linux uinput to emulate input devices.
1400// NOTE: Interacting with the physical device while these tests are running may cause
1401// the tests to fail.
1402class InputReaderIntegrationTest : public testing::Test {
1403protected:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001404 std::unique_ptr<TestInputListener> mTestListener;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001405 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001406 std::unique_ptr<InputReaderInterface> mReader;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001407
Prabir Pradhanafb7d612024-01-08 22:45:24 +00001408 constexpr static auto EVENT_HAPPENED_TIMEOUT = 2000ms;
1409 constexpr static auto EVENT_DID_NOT_HAPPEN_TIMEOUT = 30ms;
1410
Chris Yea52ade12020-08-27 16:49:20 -07001411 void SetUp() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001412#if !defined(__ANDROID__)
1413 GTEST_SKIP();
1414#endif
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001415 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001416
Arpit Singh440bf652023-08-09 09:23:43 +00001417 setupInputReader();
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001418 }
1419
Chris Yea52ade12020-08-27 16:49:20 -07001420 void TearDown() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001421#if !defined(__ANDROID__)
1422 return;
1423#endif
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001424 ASSERT_EQ(mReader->stop(), OK);
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001425 mReader.reset();
1426 mTestListener.reset();
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001427 mFakePolicy.clear();
1428 }
Prabir Pradhanda20b172022-09-26 17:01:18 +00001429
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001430 std::optional<InputDeviceInfo> waitForDevice(const std::string& deviceName) {
1431 std::chrono::time_point start = std::chrono::steady_clock::now();
1432 while (true) {
1433 const std::vector<InputDeviceInfo> inputDevices = mFakePolicy->getInputDevices();
1434 const auto& it = std::find_if(inputDevices.begin(), inputDevices.end(),
1435 [&deviceName](const InputDeviceInfo& info) {
1436 return info.getIdentifier().name == deviceName;
1437 });
1438 if (it != inputDevices.end()) {
1439 return std::make_optional(*it);
1440 }
1441 std::this_thread::sleep_for(1ms);
1442 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
1443 if (elapsed > 5s) {
1444 return {};
1445 }
1446 }
Prabir Pradhanda20b172022-09-26 17:01:18 +00001447 }
Arpit Singh440bf652023-08-09 09:23:43 +00001448
1449 void setupInputReader() {
Prabir Pradhanafb7d612024-01-08 22:45:24 +00001450 mTestListener = std::make_unique<TestInputListener>(EVENT_HAPPENED_TIMEOUT,
1451 EVENT_DID_NOT_HAPPEN_TIMEOUT);
Arpit Singh440bf652023-08-09 09:23:43 +00001452
1453 mReader = std::make_unique<InputReader>(std::make_shared<EventHub>(), mFakePolicy,
1454 *mTestListener);
1455 ASSERT_EQ(mReader->start(), OK);
1456
1457 // Since this test is run on a real device, all the input devices connected
1458 // to the test device will show up in mReader. We wait for those input devices to
1459 // show up before beginning the tests.
Arpit Singh440bf652023-08-09 09:23:43 +00001460 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyInputDevicesChangedWasCalled());
Vaibhav Devmuraric109d812024-07-10 14:21:27 +00001461 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Arpit Singh440bf652023-08-09 09:23:43 +00001462 }
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001463};
1464
1465TEST_F(InputReaderIntegrationTest, TestInvalidDevice) {
1466 // An invalid input device that is only used for this test.
1467 class InvalidUinputDevice : public UinputDevice {
1468 public:
Harry Cutts33476232023-01-30 19:57:29 +00001469 InvalidUinputDevice() : UinputDevice("Invalid Device", /*productId=*/99) {}
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001470
1471 private:
1472 void configureDevice(int fd, uinput_user_dev* device) override {}
1473 };
1474
1475 const size_t numDevices = mFakePolicy->getInputDevices().size();
1476
1477 // UinputDevice does not set any event or key bits, so InputReader should not
1478 // consider it as a valid device.
1479 std::unique_ptr<UinputDevice> invalidDevice = createUinputDevice<InvalidUinputDevice>();
1480 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesNotChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001481 ASSERT_EQ(numDevices, mFakePolicy->getInputDevices().size());
1482
1483 invalidDevice.reset();
1484 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesNotChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001485 ASSERT_EQ(numDevices, mFakePolicy->getInputDevices().size());
1486}
1487
1488TEST_F(InputReaderIntegrationTest, AddNewDevice) {
1489 const size_t initialNumDevices = mFakePolicy->getInputDevices().size();
1490
1491 std::unique_ptr<UinputHomeKey> keyboard = createUinputDevice<UinputHomeKey>();
1492 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001493 ASSERT_EQ(initialNumDevices + 1, mFakePolicy->getInputDevices().size());
1494
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001495 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001496 ASSERT_TRUE(device.has_value());
1497 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, device->getKeyboardType());
1498 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources());
1499 ASSERT_EQ(0U, device->getMotionRanges().size());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001500
1501 keyboard.reset();
1502 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001503 ASSERT_EQ(initialNumDevices, mFakePolicy->getInputDevices().size());
1504}
1505
1506TEST_F(InputReaderIntegrationTest, SendsEventsToInputListener) {
1507 std::unique_ptr<UinputHomeKey> keyboard = createUinputDevice<UinputHomeKey>();
1508 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1509
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001510 NotifyKeyArgs keyArgs;
1511 keyboard->pressAndReleaseHomeKey();
1512 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs));
1513 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001514 ASSERT_LE(keyArgs.eventTime, keyArgs.readTime);
Liana Kazanova5b8217b2024-07-18 17:44:51 +00001515
1516 int32_t prevId = keyArgs.id;
1517 nsecs_t prevTimestamp = keyArgs.eventTime;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001518
1519 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs));
1520 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
Garfield Tan1c7bc862020-01-28 13:24:04 -08001521 ASSERT_NE(prevId, keyArgs.id);
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001522 ASSERT_LE(prevTimestamp, keyArgs.eventTime);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001523 ASSERT_LE(keyArgs.eventTime, keyArgs.readTime);
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001524}
Michael Wrightd02c5b62014-02-10 15:10:22 -08001525
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001526TEST_F(InputReaderIntegrationTest, ExternalStylusesButtons) {
1527 std::unique_ptr<UinputExternalStylus> stylus = createUinputDevice<UinputExternalStylus>();
1528 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1529
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001530 const auto device = waitForDevice(stylus->getName());
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001531 ASSERT_TRUE(device.has_value());
1532
Prabir Pradhana3621852022-10-14 18:57:23 +00001533 // An external stylus with buttons should also be recognized as a keyboard.
1534 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_STYLUS, device->getSources())
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001535 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1536 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, device->getKeyboardType());
1537
1538 const auto DOWN =
1539 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD));
1540 const auto UP = AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD));
1541
1542 stylus->pressAndReleaseKey(BTN_STYLUS);
1543 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1544 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
1545 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1546 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
1547
1548 stylus->pressAndReleaseKey(BTN_STYLUS2);
1549 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1550 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_SECONDARY))));
1551 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1552 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_SECONDARY))));
1553
1554 stylus->pressAndReleaseKey(BTN_STYLUS3);
1555 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1556 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_TERTIARY))));
1557 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1558 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_TERTIARY))));
1559}
1560
Prabir Pradhan3c28b942023-08-18 20:02:01 +00001561TEST_F(InputReaderIntegrationTest, KeyboardWithStylusButtons) {
1562 std::unique_ptr<UinputKeyboard> keyboard =
1563 createUinputDevice<UinputKeyboard>("KeyboardWithStylusButtons", /*productId=*/99,
1564 std::initializer_list<int>{KEY_Q, KEY_W, KEY_E,
1565 KEY_R, KEY_T, KEY_Y,
1566 BTN_STYLUS, BTN_STYLUS2,
1567 BTN_STYLUS3});
1568 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1569
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001570 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhan3c28b942023-08-18 20:02:01 +00001571 ASSERT_TRUE(device.has_value());
1572
1573 // An alphabetical keyboard that reports stylus buttons should not be recognized as a stylus.
1574 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources())
1575 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1576 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, device->getKeyboardType());
1577}
1578
Prabir Pradhan37a819b2023-08-22 23:20:16 +00001579TEST_F(InputReaderIntegrationTest, HidUsageKeyboardIsNotAStylus) {
1580 // Create a Uinput keyboard that simulates a keyboard that can report HID usage codes. The
1581 // hid-input driver reports HID usage codes using the value for EV_MSC MSC_SCAN event.
1582 std::unique_ptr<UinputKeyboardWithHidUsage> keyboard =
1583 createUinputDevice<UinputKeyboardWithHidUsage>(
1584 std::initializer_list<int>{KEY_VOLUMEUP, KEY_VOLUMEDOWN});
1585 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1586
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001587 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhan37a819b2023-08-22 23:20:16 +00001588 ASSERT_TRUE(device.has_value());
1589
1590 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources())
1591 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1592
1593 // If a device supports reporting HID usage codes, it shouldn't automatically support
1594 // stylus keys.
1595 const std::vector<int> keycodes{AKEYCODE_STYLUS_BUTTON_PRIMARY};
1596 uint8_t outFlags[] = {0};
1597 ASSERT_TRUE(mReader->hasKeys(device->getId(), AINPUT_SOURCE_KEYBOARD, keycodes, outFlags));
1598 ASSERT_EQ(0, outFlags[0]) << "Keyboard should not have stylus button";
1599}
1600
Siarhei Vishniakoua0d2b802020-05-13 14:00:31 -07001601/**
1602 * The Steam controller sends BTN_GEAR_DOWN and BTN_GEAR_UP for the two "paddle" buttons
1603 * on the back. In this test, we make sure that BTN_GEAR_DOWN / BTN_WHEEL and BTN_GEAR_UP
1604 * are passed to the listener.
1605 */
1606static_assert(BTN_GEAR_DOWN == BTN_WHEEL);
1607TEST_F(InputReaderIntegrationTest, SendsGearDownAndUpToInputListener) {
1608 std::unique_ptr<UinputSteamController> controller = createUinputDevice<UinputSteamController>();
1609 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1610 NotifyKeyArgs keyArgs;
1611
1612 controller->pressAndReleaseKey(BTN_GEAR_DOWN);
1613 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_DOWN
1614 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_UP
1615 ASSERT_EQ(BTN_GEAR_DOWN, keyArgs.scanCode);
1616
1617 controller->pressAndReleaseKey(BTN_GEAR_UP);
1618 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_DOWN
1619 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_UP
1620 ASSERT_EQ(BTN_GEAR_UP, keyArgs.scanCode);
1621}
1622
Prabir Pradhan484d55a2022-10-14 23:17:16 +00001623// --- TouchIntegrationTest ---
1624
Arpit Singh440bf652023-08-09 09:23:43 +00001625class BaseTouchIntegrationTest : public InputReaderIntegrationTest {
Arthur Hungaab25622020-01-16 11:22:11 +08001626protected:
Arthur Hungaab25622020-01-16 11:22:11 +08001627 const std::string UNIQUE_ID = "local:0";
1628
Chris Yea52ade12020-08-27 16:49:20 -07001629 void SetUp() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001630#if !defined(__ANDROID__)
1631 GTEST_SKIP();
1632#endif
Arthur Hungaab25622020-01-16 11:22:11 +08001633 InputReaderIntegrationTest::SetUp();
1634 // At least add an internal display.
Michael Wrighta9cf4192022-12-01 23:46:39 +00001635 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
1636 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Arthur Hungaab25622020-01-16 11:22:11 +08001637
1638 mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT));
1639 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001640 const auto info = waitForDevice(mDevice->getName());
Prabir Pradhanda20b172022-09-26 17:01:18 +00001641 ASSERT_TRUE(info);
1642 mDeviceInfo = *info;
Arthur Hungaab25622020-01-16 11:22:11 +08001643 }
1644
Linnan Li13bf76a2024-05-05 19:18:02 +08001645 void setDisplayInfoAndReconfigure(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
Michael Wrighta9cf4192022-12-01 23:46:39 +00001646 ui::Rotation orientation, const std::string& uniqueId,
Arthur Hungaab25622020-01-16 11:22:11 +08001647 std::optional<uint8_t> physicalPort,
1648 ViewportType viewportType) {
Harry Cutts33476232023-01-30 19:57:29 +00001649 mFakePolicy->addDisplayViewport(displayId, width, height, orientation, /*isActive=*/true,
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00001650 uniqueId, physicalPort, viewportType);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001651 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hungaab25622020-01-16 11:22:11 +08001652 }
1653
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001654 void assertReceivedMotion(int32_t action, const std::vector<Point>& points) {
1655 NotifyMotionArgs args;
1656 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1657 EXPECT_EQ(action, args.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07001658 ASSERT_EQ(points.size(), args.getPointerCount());
1659 for (size_t i = 0; i < args.getPointerCount(); i++) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001660 EXPECT_EQ(points[i].x, args.pointerCoords[i].getX());
1661 EXPECT_EQ(points[i].y, args.pointerCoords[i].getY());
1662 }
1663 }
1664
Arthur Hungaab25622020-01-16 11:22:11 +08001665 std::unique_ptr<UinputTouchScreen> mDevice;
Prabir Pradhanda20b172022-09-26 17:01:18 +00001666 InputDeviceInfo mDeviceInfo;
Arthur Hungaab25622020-01-16 11:22:11 +08001667};
1668
Arpit Singh440bf652023-08-09 09:23:43 +00001669enum class TouchIntegrationTestDisplays { DISPLAY_INTERNAL, DISPLAY_INPUT_PORT, DISPLAY_UNIQUE_ID };
1670
1671class TouchIntegrationTest : public BaseTouchIntegrationTest,
1672 public testing::WithParamInterface<TouchIntegrationTestDisplays> {
1673protected:
1674 static constexpr std::optional<uint8_t> DISPLAY_PORT = 0;
1675 const std::string INPUT_PORT = "uinput_touch/input0";
1676
1677 void SetUp() override {
1678#if !defined(__ANDROID__)
1679 GTEST_SKIP();
1680#endif
1681 if (GetParam() == TouchIntegrationTestDisplays::DISPLAY_INTERNAL) {
1682 BaseTouchIntegrationTest::SetUp();
1683 return;
1684 }
1685
1686 // setup policy with a input-port or UniqueId association to the display
1687 bool isInputPortAssociation =
1688 GetParam() == TouchIntegrationTestDisplays::DISPLAY_INPUT_PORT;
1689
1690 mFakePolicy = sp<FakeInputReaderPolicy>::make();
1691 if (isInputPortAssociation) {
1692 mFakePolicy->addInputPortAssociation(INPUT_PORT, DISPLAY_PORT.value());
1693 } else {
1694 mFakePolicy->addInputUniqueIdAssociation(INPUT_PORT, UNIQUE_ID);
1695 }
Arpit Singh440bf652023-08-09 09:23:43 +00001696
1697 InputReaderIntegrationTest::setupInputReader();
1698
1699 mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT),
1700 INPUT_PORT);
1701 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1702
1703 // Add a display linked to a physical port or UniqueId.
1704 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
1705 UNIQUE_ID, isInputPortAssociation ? DISPLAY_PORT : NO_PORT,
1706 ViewportType::INTERNAL);
1707 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001708 const auto info = waitForDevice(mDevice->getName());
Arpit Singh440bf652023-08-09 09:23:43 +00001709 ASSERT_TRUE(info);
1710 mDeviceInfo = *info;
1711 }
1712};
1713
1714TEST_P(TouchIntegrationTest, MultiTouchDeviceSource) {
Prabir Pradhanf9a41282022-10-25 17:15:50 +00001715 // The UinputTouchScreen is an MT device that supports MT_TOOL_TYPE and also supports stylus
1716 // buttons. It should show up as a touchscreen, stylus, and keyboard (for reporting button
1717 // presses).
1718 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD,
1719 mDeviceInfo.getSources());
1720}
1721
Arpit Singh440bf652023-08-09 09:23:43 +00001722TEST_P(TouchIntegrationTest, InputEvent_ProcessSingleTouch) {
Arthur Hungaab25622020-01-16 11:22:11 +08001723 NotifyMotionArgs args;
1724 const Point centerPoint = mDevice->getCenterPoint();
1725
1726 // ACTION_DOWN
Arthur Hung9ad18942021-06-19 02:04:46 +00001727 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001728 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001729 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001730 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1731 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1732
1733 // ACTION_MOVE
1734 mDevice->sendMove(centerPoint + Point(1, 1));
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001735 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001736 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1737 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1738
1739 // ACTION_UP
1740 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001741 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001742 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1743 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
1744}
1745
Arpit Singh440bf652023-08-09 09:23:43 +00001746TEST_P(TouchIntegrationTest, InputEvent_ProcessMultiTouch) {
Arthur Hungaab25622020-01-16 11:22:11 +08001747 NotifyMotionArgs args;
1748 const Point centerPoint = mDevice->getCenterPoint();
1749
1750 // ACTION_DOWN
Arthur Hung9ad18942021-06-19 02:04:46 +00001751 mDevice->sendSlot(FIRST_SLOT);
1752 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001753 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001754 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001755 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1756 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1757
1758 // ACTION_POINTER_DOWN (Second slot)
1759 const Point secondPoint = centerPoint + Point(100, 100);
1760 mDevice->sendSlot(SECOND_SLOT);
1761 mDevice->sendTrackingId(SECOND_TRACKING_ID);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001762 mDevice->sendDown(secondPoint);
1763 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001764 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001765 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001766
1767 // ACTION_MOVE (Second slot)
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001768 mDevice->sendMove(secondPoint + Point(1, 1));
1769 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001770 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1771 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1772
1773 // ACTION_POINTER_UP (Second slot)
arthurhungcc7f9802020-04-30 17:55:40 +08001774 mDevice->sendPointerUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001775 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001776 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001777 ASSERT_EQ(ACTION_POINTER_1_UP, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001778
1779 // ACTION_UP
1780 mDevice->sendSlot(FIRST_SLOT);
1781 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001782 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001783 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1784 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
1785}
1786
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001787/**
1788 * What happens when a pointer goes up while another pointer moves in the same frame? Are POINTER_UP
1789 * events guaranteed to contain the same data as a preceding MOVE, or can they contain different
1790 * data?
1791 * In this test, we try to send a change in coordinates in Pointer 0 in the same frame as the
1792 * liftoff of Pointer 1. We check that POINTER_UP event is generated first, and the MOVE event
1793 * for Pointer 0 only is generated after.
1794 * Suppose we are only interested in learning the movement of Pointer 0. If we only observe MOVE
1795 * events, we will not miss any information.
1796 * Even though the Pointer 1 up event contains updated Pointer 0 coordinates, there is another MOVE
1797 * event generated afterwards that contains the newest movement of pointer 0.
1798 * This is important for palm rejection. If there is a subsequent InputListener stage that detects
1799 * palms, and wants to cancel Pointer 1, then it is safe to simply drop POINTER_1_UP event without
1800 * losing information about non-palm pointers.
1801 */
Arpit Singh440bf652023-08-09 09:23:43 +00001802TEST_P(TouchIntegrationTest, MultiTouch_PointerMoveAndSecondPointerUp) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001803 NotifyMotionArgs args;
1804 const Point centerPoint = mDevice->getCenterPoint();
1805
1806 // ACTION_DOWN
1807 mDevice->sendSlot(FIRST_SLOT);
1808 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1809 mDevice->sendDown(centerPoint);
1810 mDevice->sendSync();
1811 assertReceivedMotion(AMOTION_EVENT_ACTION_DOWN, {centerPoint});
1812
1813 // ACTION_POINTER_DOWN (Second slot)
1814 const Point secondPoint = centerPoint + Point(100, 100);
1815 mDevice->sendSlot(SECOND_SLOT);
1816 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1817 mDevice->sendDown(secondPoint);
1818 mDevice->sendSync();
1819 assertReceivedMotion(ACTION_POINTER_1_DOWN, {centerPoint, secondPoint});
1820
1821 // ACTION_MOVE (First slot)
1822 mDevice->sendSlot(FIRST_SLOT);
1823 mDevice->sendMove(centerPoint + Point(5, 5));
1824 // ACTION_POINTER_UP (Second slot)
1825 mDevice->sendSlot(SECOND_SLOT);
1826 mDevice->sendPointerUp();
1827 // Send a single sync for the above 2 pointer updates
1828 mDevice->sendSync();
1829
1830 // First, we should get POINTER_UP for the second pointer
1831 assertReceivedMotion(ACTION_POINTER_1_UP,
1832 {/*first pointer */ centerPoint + Point(5, 5),
1833 /*second pointer*/ secondPoint});
1834
1835 // Next, the MOVE event for the first pointer
1836 assertReceivedMotion(AMOTION_EVENT_ACTION_MOVE, {centerPoint + Point(5, 5)});
1837}
1838
1839/**
1840 * Similar scenario as above. The difference is that when the second pointer goes up, it will first
1841 * move, and then it will go up, all in the same frame.
1842 * In this scenario, the movement of the second pointer just prior to liftoff is ignored, and never
1843 * gets sent to the listener.
1844 */
Arpit Singh440bf652023-08-09 09:23:43 +00001845TEST_P(TouchIntegrationTest, MultiTouch_PointerMoveAndSecondPointerMoveAndUp) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001846 NotifyMotionArgs args;
1847 const Point centerPoint = mDevice->getCenterPoint();
1848
1849 // ACTION_DOWN
1850 mDevice->sendSlot(FIRST_SLOT);
1851 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1852 mDevice->sendDown(centerPoint);
1853 mDevice->sendSync();
1854 assertReceivedMotion(AMOTION_EVENT_ACTION_DOWN, {centerPoint});
1855
1856 // ACTION_POINTER_DOWN (Second slot)
1857 const Point secondPoint = centerPoint + Point(100, 100);
1858 mDevice->sendSlot(SECOND_SLOT);
1859 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1860 mDevice->sendDown(secondPoint);
1861 mDevice->sendSync();
1862 assertReceivedMotion(ACTION_POINTER_1_DOWN, {centerPoint, secondPoint});
1863
1864 // ACTION_MOVE (First slot)
1865 mDevice->sendSlot(FIRST_SLOT);
1866 mDevice->sendMove(centerPoint + Point(5, 5));
1867 // ACTION_POINTER_UP (Second slot)
1868 mDevice->sendSlot(SECOND_SLOT);
1869 mDevice->sendMove(secondPoint + Point(6, 6));
1870 mDevice->sendPointerUp();
1871 // Send a single sync for the above 2 pointer updates
1872 mDevice->sendSync();
1873
1874 // First, we should get POINTER_UP for the second pointer
1875 // The movement of the second pointer during the liftoff frame is ignored.
1876 // The coordinates 'secondPoint + Point(6, 6)' are never sent to the listener.
1877 assertReceivedMotion(ACTION_POINTER_1_UP,
1878 {/*first pointer */ centerPoint + Point(5, 5),
1879 /*second pointer*/ secondPoint});
1880
1881 // Next, the MOVE event for the first pointer
1882 assertReceivedMotion(AMOTION_EVENT_ACTION_MOVE, {centerPoint + Point(5, 5)});
1883}
1884
Arpit Singh440bf652023-08-09 09:23:43 +00001885TEST_P(TouchIntegrationTest, InputEvent_ProcessPalm) {
Arthur Hungaab25622020-01-16 11:22:11 +08001886 NotifyMotionArgs args;
1887 const Point centerPoint = mDevice->getCenterPoint();
1888
1889 // ACTION_DOWN
arthurhungcc7f9802020-04-30 17:55:40 +08001890 mDevice->sendSlot(FIRST_SLOT);
1891 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001892 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001893 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001894 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1895 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1896
arthurhungcc7f9802020-04-30 17:55:40 +08001897 // ACTION_POINTER_DOWN (second slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001898 const Point secondPoint = centerPoint + Point(100, 100);
1899 mDevice->sendSlot(SECOND_SLOT);
1900 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1901 mDevice->sendDown(secondPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001902 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001903 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001904 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001905
arthurhungcc7f9802020-04-30 17:55:40 +08001906 // ACTION_MOVE (second slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001907 mDevice->sendMove(secondPoint + Point(1, 1));
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001908 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001909 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1910 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1911
arthurhungcc7f9802020-04-30 17:55:40 +08001912 // Send MT_TOOL_PALM (second slot), which indicates that the touch IC has determined this to be
1913 // a palm event.
1914 // Expect to receive the ACTION_POINTER_UP with cancel flag.
Arthur Hungaab25622020-01-16 11:22:11 +08001915 mDevice->sendToolType(MT_TOOL_PALM);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001916 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001917 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001918 ASSERT_EQ(ACTION_POINTER_1_UP, args.action);
arthurhungcc7f9802020-04-30 17:55:40 +08001919 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, args.flags);
Arthur Hungaab25622020-01-16 11:22:11 +08001920
arthurhungcc7f9802020-04-30 17:55:40 +08001921 // Send up to second slot, expect first slot send moving.
1922 mDevice->sendPointerUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001923 mDevice->sendSync();
arthurhungcc7f9802020-04-30 17:55:40 +08001924 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1925 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001926
arthurhungcc7f9802020-04-30 17:55:40 +08001927 // Send ACTION_UP (first slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001928 mDevice->sendSlot(FIRST_SLOT);
1929 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001930 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001931
arthurhungcc7f9802020-04-30 17:55:40 +08001932 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1933 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001934}
1935
Prabir Pradhanc09ec6d2023-08-14 22:31:43 +00001936/**
1937 * Some drivers historically have reported axis values outside of the range specified in the
1938 * evdev axis info. Ensure we don't crash when this happens. For example, a driver may report a
1939 * pressure value greater than the reported maximum, since it unclear what specific meaning the
1940 * maximum value for pressure has (beyond the maximum value that can be produced by a sensor),
1941 * and no units for pressure (resolution) is specified by the evdev documentation.
1942 */
1943TEST_P(TouchIntegrationTest, AcceptsAxisValuesOutsideReportedRange) {
1944 const Point centerPoint = mDevice->getCenterPoint();
1945
1946 // Down with pressure outside the reported range
1947 mDevice->sendSlot(FIRST_SLOT);
1948 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1949 mDevice->sendDown(centerPoint);
1950 mDevice->sendPressure(UinputTouchScreen::RAW_PRESSURE_MAX + 2);
1951 mDevice->sendSync();
1952 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1953 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
1954
1955 // Move to a point outside the reported range
1956 mDevice->sendMove(Point(DISPLAY_WIDTH, DISPLAY_HEIGHT) + Point(1, 1));
1957 mDevice->sendSync();
1958 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1959 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
1960
1961 // Up
1962 mDevice->sendUp();
1963 mDevice->sendSync();
1964 ASSERT_NO_FATAL_FAILURE(
1965 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
1966}
1967
Arpit Singh440bf652023-08-09 09:23:43 +00001968TEST_P(TouchIntegrationTest, NotifiesPolicyWhenStylusGestureStarted) {
Prabir Pradhanda20b172022-09-26 17:01:18 +00001969 const Point centerPoint = mDevice->getCenterPoint();
1970
1971 // Send down with the pen tool selected. The policy should be notified of the stylus presence.
1972 mDevice->sendSlot(FIRST_SLOT);
1973 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1974 mDevice->sendToolType(MT_TOOL_PEN);
1975 mDevice->sendDown(centerPoint);
1976 mDevice->sendSync();
1977 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1978 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001979 WithToolType(ToolType::STYLUS))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00001980
1981 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotified(mDeviceInfo.getId()));
1982
1983 // Release the stylus touch.
1984 mDevice->sendUp();
1985 mDevice->sendSync();
1986 ASSERT_NO_FATAL_FAILURE(
1987 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
1988
1989 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotNotified());
1990
1991 // Touch down with the finger, without the pen tool selected. The policy is not notified.
1992 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1993 mDevice->sendToolType(MT_TOOL_FINGER);
1994 mDevice->sendDown(centerPoint);
1995 mDevice->sendSync();
1996 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1997 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001998 WithToolType(ToolType::FINGER))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00001999
2000 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotNotified());
2001
2002 mDevice->sendUp();
2003 mDevice->sendSync();
2004 ASSERT_NO_FATAL_FAILURE(
2005 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2006
2007 // Send a move event with the stylus tool without BTN_TOUCH to generate a hover enter.
2008 // The policy should be notified of the stylus presence.
2009 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2010 mDevice->sendToolType(MT_TOOL_PEN);
2011 mDevice->sendMove(centerPoint);
2012 mDevice->sendSync();
2013 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2014 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002015 WithToolType(ToolType::STYLUS))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00002016
2017 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotified(mDeviceInfo.getId()));
2018}
2019
Arpit Singh440bf652023-08-09 09:23:43 +00002020TEST_P(TouchIntegrationTest, ExternalStylusConnectedDuringTouchGesture) {
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002021 const Point centerPoint = mDevice->getCenterPoint();
2022
2023 // Down
2024 mDevice->sendSlot(FIRST_SLOT);
2025 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2026 mDevice->sendDown(centerPoint);
2027 mDevice->sendSync();
2028 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2029 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
2030
2031 // Move
2032 mDevice->sendMove(centerPoint + Point(1, 1));
2033 mDevice->sendSync();
2034 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2035 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
2036
2037 // Connecting an external stylus mid-gesture should not interrupt the ongoing gesture stream.
2038 auto externalStylus = createUinputDevice<UinputExternalStylus>();
2039 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002040 const auto stylusInfo = waitForDevice(externalStylus->getName());
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002041 ASSERT_TRUE(stylusInfo);
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002042
2043 // Move
2044 mDevice->sendMove(centerPoint + Point(2, 2));
2045 mDevice->sendSync();
2046 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2047 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
2048
2049 // Disconnecting an external stylus mid-gesture should not interrupt the ongoing gesture stream.
2050 externalStylus.reset();
2051 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002052 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2053
2054 // Up
2055 mDevice->sendUp();
2056 mDevice->sendSync();
2057 ASSERT_NO_FATAL_FAILURE(
2058 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2059
2060 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2061}
2062
Arpit Singh440bf652023-08-09 09:23:43 +00002063INSTANTIATE_TEST_SUITE_P(TouchIntegrationTestDisplayVariants, TouchIntegrationTest,
2064 testing::Values(TouchIntegrationTestDisplays::DISPLAY_INTERNAL,
2065 TouchIntegrationTestDisplays::DISPLAY_INPUT_PORT,
2066 TouchIntegrationTestDisplays::DISPLAY_UNIQUE_ID));
2067
Prabir Pradhan124ea442022-10-28 20:27:44 +00002068// --- StylusButtonIntegrationTest ---
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002069
Prabir Pradhan124ea442022-10-28 20:27:44 +00002070// Verify the behavior of button presses reported by various kinds of styluses, including buttons
2071// reported by the touchscreen's device, by a fused external stylus, and by an un-fused external
2072// stylus.
2073template <typename UinputStylusDevice>
Arpit Singh440bf652023-08-09 09:23:43 +00002074class StylusButtonIntegrationTest : public BaseTouchIntegrationTest {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002075protected:
2076 void SetUp() override {
2077#if !defined(__ANDROID__)
2078 GTEST_SKIP();
2079#endif
Arpit Singh440bf652023-08-09 09:23:43 +00002080 BaseTouchIntegrationTest::SetUp();
Prabir Pradhan124ea442022-10-28 20:27:44 +00002081 mTouchscreen = mDevice.get();
2082 mTouchscreenInfo = mDeviceInfo;
2083
2084 setUpStylusDevice();
2085 }
2086
2087 UinputStylusDevice* mStylus{nullptr};
2088 InputDeviceInfo mStylusInfo{};
2089
2090 UinputTouchScreen* mTouchscreen{nullptr};
2091 InputDeviceInfo mTouchscreenInfo{};
2092
2093private:
2094 // When we are attempting to test stylus button events that are sent from the touchscreen,
2095 // use the same Uinput device for the touchscreen and the stylus.
2096 template <typename T = UinputStylusDevice>
2097 std::enable_if_t<std::is_same_v<UinputTouchScreen, T>, void> setUpStylusDevice() {
2098 mStylus = mDevice.get();
2099 mStylusInfo = mDeviceInfo;
2100 }
2101
2102 // When we are attempting to stylus buttons from an external stylus being merged with touches
2103 // from a touchscreen, create a new Uinput device through which stylus buttons can be injected.
2104 template <typename T = UinputStylusDevice>
2105 std::enable_if_t<!std::is_same_v<UinputTouchScreen, T>, void> setUpStylusDevice() {
2106 mStylusDeviceLifecycleTracker = createUinputDevice<T>();
2107 mStylus = mStylusDeviceLifecycleTracker.get();
2108 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002109 const auto info = waitForDevice(mStylus->getName());
Prabir Pradhan124ea442022-10-28 20:27:44 +00002110 ASSERT_TRUE(info);
2111 mStylusInfo = *info;
2112 }
2113
2114 std::unique_ptr<UinputStylusDevice> mStylusDeviceLifecycleTracker{};
2115
2116 // Hide the base class's device to expose it with a different name for readability.
Arpit Singh440bf652023-08-09 09:23:43 +00002117 using BaseTouchIntegrationTest::mDevice;
2118 using BaseTouchIntegrationTest::mDeviceInfo;
Prabir Pradhan124ea442022-10-28 20:27:44 +00002119};
2120
2121using StylusButtonIntegrationTestTypes =
2122 ::testing::Types<UinputTouchScreen, UinputExternalStylus, UinputExternalStylusWithPressure>;
2123TYPED_TEST_SUITE(StylusButtonIntegrationTest, StylusButtonIntegrationTestTypes);
2124
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002125TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsGenerateKeyEvents) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002126 const auto stylusId = TestFixture::mStylusInfo.getId();
2127
2128 TestFixture::mStylus->pressKey(BTN_STYLUS);
2129 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2130 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2131 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2132
2133 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2134 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002135 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002136 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002137}
2138
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002139TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingTouchGesture) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002140 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2141 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2142 const auto stylusId = TestFixture::mStylusInfo.getId();
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002143
2144 // Press the stylus button.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002145 TestFixture::mStylus->pressKey(BTN_STYLUS);
2146 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002147 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002148 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002149
2150 // Start and finish a stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002151 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2152 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2153 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2154 TestFixture::mTouchscreen->sendDown(centerPoint);
2155 TestFixture::mTouchscreen->sendSync();
2156 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002157 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002158 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002159 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2160 WithDeviceId(touchscreenId))));
2161 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002162 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002163 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002164 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2165 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002166
Prabir Pradhan124ea442022-10-28 20:27:44 +00002167 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2168 TestFixture::mTouchscreen->sendSync();
2169 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002170 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002171 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002172 WithDeviceId(touchscreenId))));
2173 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002174 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002175 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002176 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002177
2178 // Release the stylus button.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002179 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2180 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002181 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002182 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002183}
2184
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002185TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingHoveringTouchGesture) {
Prabir Pradhan9a561c22022-11-07 16:11:23 +00002186 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2187 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2188 const auto stylusId = TestFixture::mStylusInfo.getId();
2189 auto toolTypeDevice =
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002190 AllOf(WithToolType(ToolType::STYLUS), WithDeviceId(touchscreenId));
Prabir Pradhan9a561c22022-11-07 16:11:23 +00002191
2192 // Press the stylus button.
2193 TestFixture::mStylus->pressKey(BTN_STYLUS);
2194 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2195 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2196 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2197
2198 // Start hovering with the stylus.
2199 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2200 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2201 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2202 TestFixture::mTouchscreen->sendMove(centerPoint);
2203 TestFixture::mTouchscreen->sendSync();
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 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2211 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
2212 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2213
2214 // Touch down with the stylus.
2215 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2216 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2217 TestFixture::mTouchscreen->sendDown(centerPoint);
2218 TestFixture::mTouchscreen->sendSync();
2219 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2220 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
2221 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2222
2223 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2224 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
2225 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2226
2227 // Stop touching with the stylus, and start hovering.
2228 TestFixture::mTouchscreen->sendUp();
2229 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2230 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2231 TestFixture::mTouchscreen->sendMove(centerPoint);
2232 TestFixture::mTouchscreen->sendSync();
2233 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2234 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_UP),
2235 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2236 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2237 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2238 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2239 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2240 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2241 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2242
2243 // Stop hovering.
2244 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2245 TestFixture::mTouchscreen->sendSync();
2246 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2247 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
2248 WithButtonState(0))));
2249 // TODO(b/257971675): Fix inconsistent button state when exiting hover.
2250 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2251 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
2252 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2253
2254 // Release the stylus button.
2255 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2256 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2257 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
2258 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2259}
2260
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002261TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsWithinTouchGesture) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002262 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2263 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2264 const auto stylusId = TestFixture::mStylusInfo.getId();
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002265
2266 // Start a stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002267 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2268 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2269 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2270 TestFixture::mTouchscreen->sendDown(centerPoint);
2271 TestFixture::mTouchscreen->sendSync();
2272 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002273 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002274 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002275 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002276
2277 // Press and release a stylus button. Each change in button state also generates a MOVE event.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002278 TestFixture::mStylus->pressKey(BTN_STYLUS);
2279 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002280 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002281 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2282 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002283 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002284 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002285 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2286 WithDeviceId(touchscreenId))));
2287 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002288 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002289 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002290 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2291 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002292
Prabir Pradhan124ea442022-10-28 20:27:44 +00002293 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2294 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002295 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002296 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2297 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002298 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002299 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002300 WithDeviceId(touchscreenId))));
2301 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002302 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002303 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002304 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002305
2306 // Finish the stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002307 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2308 TestFixture::mTouchscreen->sendSync();
2309 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002310 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002311 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002312 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002313}
2314
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002315TYPED_TEST(StylusButtonIntegrationTest, StylusButtonMotionEventsDisabled) {
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002316 TestFixture::mFakePolicy->setStylusButtonMotionEventsEnabled(false);
2317 TestFixture::mReader->requestRefreshConfiguration(
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002318 InputReaderConfiguration::Change::STYLUS_BUTTON_REPORTING);
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002319
2320 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2321 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2322 const auto stylusId = TestFixture::mStylusInfo.getId();
2323
2324 // Start a stylus gesture. By the time this event is processed, the configuration change that
2325 // was requested is guaranteed to be completed.
2326 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2327 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2328 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2329 TestFixture::mTouchscreen->sendDown(centerPoint);
2330 TestFixture::mTouchscreen->sendSync();
2331 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2332 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002333 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002334 WithDeviceId(touchscreenId))));
2335
2336 // Press and release a stylus button. Each change only generates a MOVE motion event.
2337 // Key events are unaffected.
2338 TestFixture::mStylus->pressKey(BTN_STYLUS);
2339 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2340 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2341 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2342 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2343 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002344 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002345 WithDeviceId(touchscreenId))));
2346
2347 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2348 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2349 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
2350 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2351 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2352 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002353 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002354 WithDeviceId(touchscreenId))));
2355
2356 // Finish the stylus gesture.
2357 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2358 TestFixture::mTouchscreen->sendSync();
2359 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2360 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002361 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002362 WithDeviceId(touchscreenId))));
2363}
2364
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002365// --- ExternalStylusIntegrationTest ---
2366
2367// Verify the behavior of an external stylus. An external stylus can report pressure or button
2368// data independently of the touchscreen, which is then sent as a MotionEvent as part of an
2369// ongoing stylus gesture that is being emitted by the touchscreen.
Arpit Singh440bf652023-08-09 09:23:43 +00002370using ExternalStylusIntegrationTest = BaseTouchIntegrationTest;
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002371
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002372TEST_F(ExternalStylusIntegrationTest, ExternalStylusConnectionChangesTouchscreenSource) {
2373 // Create an external stylus capable of reporting pressure data that
2374 // should be fused with a touch pointer.
2375 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2376 createUinputDevice<UinputExternalStylusWithPressure>();
2377 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002378 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002379 ASSERT_TRUE(stylusInfo);
2380
2381 // Connecting an external stylus changes the source of the touchscreen.
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002382 const auto deviceInfo = waitForDevice(mDevice->getName());
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002383 ASSERT_TRUE(deviceInfo);
2384 ASSERT_TRUE(isFromSource(deviceInfo->getSources(), STYLUS_FUSION_SOURCE));
2385}
2386
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002387TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureReported) {
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002388 const Point centerPoint = mDevice->getCenterPoint();
2389
2390 // Create an external stylus capable of reporting pressure data that
2391 // should be fused with a touch pointer.
2392 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2393 createUinputDevice<UinputExternalStylusWithPressure>();
2394 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002395 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002396 ASSERT_TRUE(stylusInfo);
2397
2398 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2399
2400 const auto touchscreenId = mDeviceInfo.getId();
2401
2402 // Set a pressure value on the stylus. It doesn't generate any events.
2403 const auto& RAW_PRESSURE_MAX = UinputExternalStylusWithPressure::RAW_PRESSURE_MAX;
2404 stylus->setPressure(100);
2405 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2406
2407 // Start a finger gesture, and ensure it shows up as stylus gesture
2408 // with the pressure set by the external stylus.
Dominik Laskowski2f01d772022-03-23 16:01:29 -07002409 mDevice->sendSlot(FIRST_SLOT);
Chris Ye1b0c7342020-07-28 21:57:03 -07002410 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002411 mDevice->sendToolType(MT_TOOL_FINGER);
Prabir Pradhanb54ffb22022-10-27 18:03:34 +00002412 mDevice->sendDown(centerPoint);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002413 mDevice->sendSync();
2414 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002415 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithToolType(ToolType::STYLUS),
2416 WithButtonState(0), WithSource(STYLUS_FUSION_SOURCE), WithDeviceId(touchscreenId),
2417 WithPressure(100.f / RAW_PRESSURE_MAX))));
Dominik Laskowski2f01d772022-03-23 16:01:29 -07002418
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002419 // Change the pressure on the external stylus, and ensure the touchscreen generates a MOVE
2420 // event with the updated pressure.
2421 stylus->setPressure(200);
Vaibhav Devmuraridd82b8e2022-08-16 15:34:01 +00002422 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002423 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithToolType(ToolType::STYLUS),
2424 WithButtonState(0), WithSource(STYLUS_FUSION_SOURCE), WithDeviceId(touchscreenId),
2425 WithPressure(200.f / RAW_PRESSURE_MAX))));
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002426
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002427 // The external stylus did not generate any events.
2428 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2429 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
2430}
2431
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002432TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureNotReported) {
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002433 const Point centerPoint = mDevice->getCenterPoint();
2434
2435 // Create an external stylus capable of reporting pressure data that
2436 // should be fused with a touch pointer.
2437 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2438 createUinputDevice<UinputExternalStylusWithPressure>();
2439 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002440 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002441 ASSERT_TRUE(stylusInfo);
2442
2443 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2444
2445 const auto touchscreenId = mDeviceInfo.getId();
2446
2447 // Set a pressure value of 0 on the stylus. It doesn't generate any events.
2448 const auto& RAW_PRESSURE_MAX = UinputExternalStylusWithPressure::RAW_PRESSURE_MAX;
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002449 // Send a non-zero value first to prevent the kernel from consuming the zero event.
2450 stylus->setPressure(100);
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002451 stylus->setPressure(0);
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002452 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002453
2454 // Start a finger gesture. The touch device will withhold generating any touches for
2455 // up to 72 milliseconds while waiting for pressure data from the external stylus.
2456 mDevice->sendSlot(FIRST_SLOT);
2457 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2458 mDevice->sendToolType(MT_TOOL_FINGER);
2459 mDevice->sendDown(centerPoint);
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002460 const auto syncTime = std::chrono::system_clock::now();
2461 // After 72 ms, the event *will* be generated. If we wait the full 72 ms to check that NO event
2462 // is generated in that period, there will be a race condition between the event being generated
2463 // and the test's wait timeout expiring. Thus, we wait for a shorter duration in the test, which
2464 // will reduce the liklihood of the race condition occurring.
2465 const auto waitUntilTimeForNoEvent =
2466 syncTime + std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT / 2));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07002467 mDevice->sendSync();
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002468 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled(waitUntilTimeForNoEvent));
Michael Wrightd02c5b62014-02-10 15:10:22 -08002469
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002470 // Since the external stylus did not report a pressure value within the timeout,
2471 // it shows up as a finger pointer.
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002472 const auto waitUntilTimeForEvent = syncTime +
2473 std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT)) + EVENT_HAPPENED_TIMEOUT;
2474 ASSERT_NO_FATAL_FAILURE(
2475 mTestListener->assertNotifyMotionWasCalled(AllOf(WithMotionAction(
2476 AMOTION_EVENT_ACTION_DOWN),
2477 WithSource(AINPUT_SOURCE_TOUCHSCREEN |
2478 AINPUT_SOURCE_STYLUS),
2479 WithToolType(ToolType::FINGER),
2480 WithDeviceId(touchscreenId),
2481 WithPressure(1.f)),
2482 waitUntilTimeForEvent));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002483
2484 // Change the pressure on the external stylus. Since the pressure was not present at the start
2485 // of the gesture, it is ignored for now.
2486 stylus->setPressure(200);
2487 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2488
2489 // Finish the finger gesture.
Michael Wrightd02c5b62014-02-10 15:10:22 -08002490 mDevice->sendTrackingId(INVALID_TRACKING_ID);
2491 mDevice->sendSync();
2492 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2493 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002494 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002495 WithToolType(ToolType::FINGER))));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002496
2497 // Start a new gesture. Since we have a valid pressure value, it shows up as a stylus.
2498 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2499 mDevice->sendToolType(MT_TOOL_FINGER);
2500 mDevice->sendDown(centerPoint);
2501 mDevice->sendSync();
2502 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002503 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithSource(STYLUS_FUSION_SOURCE),
2504 WithToolType(ToolType::STYLUS), WithButtonState(0), WithDeviceId(touchscreenId),
2505 WithPressure(200.f / RAW_PRESSURE_MAX))));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002506
2507 // The external stylus did not generate any events.
2508 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2509 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002510}
Siarhei Vishniakou1983a712021-06-04 19:27:09 +00002511
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002512TEST_F(ExternalStylusIntegrationTest, UnfusedExternalStylus) {
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002513 const Point centerPoint = mDevice->getCenterPoint();
2514
2515 // Create an external stylus device that does not support pressure. It should not affect any
2516 // touch pointers.
2517 std::unique_ptr<UinputExternalStylus> stylus = createUinputDevice<UinputExternalStylus>();
2518 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002519 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002520 ASSERT_TRUE(stylusInfo);
2521
2522 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2523
2524 const auto touchscreenId = mDeviceInfo.getId();
2525
2526 // Start a finger gesture and ensure a finger pointer is generated for it, without waiting for
2527 // pressure data from the external stylus.
2528 mDevice->sendSlot(FIRST_SLOT);
2529 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2530 mDevice->sendToolType(MT_TOOL_FINGER);
2531 mDevice->sendDown(centerPoint);
2532 auto waitUntil = std::chrono::system_clock::now() +
2533 std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT));
2534 mDevice->sendSync();
2535 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002536 mTestListener->assertNotifyMotionWasCalled(AllOf(WithMotionAction(
2537 AMOTION_EVENT_ACTION_DOWN),
2538 WithToolType(ToolType::FINGER),
2539 WithSource(AINPUT_SOURCE_TOUCHSCREEN |
2540 AINPUT_SOURCE_STYLUS),
2541 WithButtonState(0),
2542 WithDeviceId(touchscreenId),
2543 WithPressure(1.f)),
2544 waitUntil));
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002545
2546 // The external stylus did not generate any events.
2547 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2548 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
2549}
2550
Michael Wrightd02c5b62014-02-10 15:10:22 -08002551// --- InputDeviceTest ---
2552class InputDeviceTest : public testing::Test {
2553protected:
2554 static const char* DEVICE_NAME;
2555 static const char* DEVICE_LOCATION;
2556 static const int32_t DEVICE_ID;
2557 static const int32_t DEVICE_GENERATION;
2558 static const int32_t DEVICE_CONTROLLER_NUMBER;
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002559 static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002560 static const int32_t EVENTHUB_ID;
2561 static const std::string DEVICE_BLUETOOTH_ADDRESS;
2562
2563 std::shared_ptr<FakeEventHub> mFakeEventHub;
2564 sp<FakeInputReaderPolicy> mFakePolicy;
2565 std::unique_ptr<TestInputListener> mFakeListener;
2566 std::unique_ptr<InstrumentedInputReader> mReader;
2567 std::shared_ptr<InputDevice> mDevice;
2568
2569 void SetUp() override {
2570 mFakeEventHub = std::make_unique<FakeEventHub>();
2571 mFakePolicy = sp<FakeInputReaderPolicy>::make();
2572 mFakeListener = std::make_unique<TestInputListener>();
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002573 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Michael Wrightd02c5b62014-02-10 15:10:22 -08002574 *mFakeListener);
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002575 InputDeviceIdentifier identifier;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002576 identifier.name = DEVICE_NAME;
2577 identifier.location = DEVICE_LOCATION;
2578 identifier.bluetoothAddress = DEVICE_BLUETOOTH_ADDRESS;
2579 mDevice = std::make_shared<InputDevice>(mReader->getContext(), DEVICE_ID, DEVICE_GENERATION,
2580 identifier);
2581 mReader->pushNextDevice(mDevice);
2582 mFakeEventHub->addDevice(EVENTHUB_ID, DEVICE_NAME, ftl::Flags<InputDeviceClass>(0));
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002583 mReader->loopOnce();
Michael Wrightd02c5b62014-02-10 15:10:22 -08002584 }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002585
2586 void TearDown() override {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002587 mFakeListener.reset();
2588 mFakePolicy.clear();
2589 }
2590};
2591
2592const char* InputDeviceTest::DEVICE_NAME = "device";
2593const char* InputDeviceTest::DEVICE_LOCATION = "USB1";
2594const int32_t InputDeviceTest::DEVICE_ID = END_RESERVED_ID + 1000;
2595const int32_t InputDeviceTest::DEVICE_GENERATION = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002596const int32_t InputDeviceTest::DEVICE_CONTROLLER_NUMBER = 0;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002597const ftl::Flags<InputDeviceClass> InputDeviceTest::DEVICE_CLASSES =
2598 InputDeviceClass::KEYBOARD | InputDeviceClass::TOUCH | InputDeviceClass::JOYSTICK;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002599const int32_t InputDeviceTest::EVENTHUB_ID = 1;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002600const std::string InputDeviceTest::DEVICE_BLUETOOTH_ADDRESS = "11:AA:22:BB:33:CC";
2601
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002602TEST_F(InputDeviceTest, ImmutableProperties) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002603 ASSERT_EQ(DEVICE_ID, mDevice->getId());
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002604 ASSERT_STREQ(DEVICE_NAME, mDevice->getName().c_str());
2605 ASSERT_EQ(ftl::Flags<InputDeviceClass>(0), mDevice->getClasses());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002606}
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002607
Michael Wrightd02c5b62014-02-10 15:10:22 -08002608TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsFalse) {
2609 ASSERT_EQ(mDevice->isEnabled(), false);
2610}
2611
2612TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
2613 // Configuration.
2614 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002615 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002616
2617 // Reset.
2618 unused += mDevice->reset(ARBITRARY_TIME);
2619
2620 NotifyDeviceResetArgs resetArgs;
2621 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
2622 ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
2623 ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
2624
2625 // Metadata.
2626 ASSERT_TRUE(mDevice->isIgnored());
2627 ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mDevice->getSources());
2628
2629 InputDeviceInfo info = mDevice->getDeviceInfo();
2630 ASSERT_EQ(DEVICE_ID, info.getId());
2631 ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.c_str());
2632 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NONE, info.getKeyboardType());
2633 ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, info.getSources());
2634
2635 // State queries.
2636 ASSERT_EQ(0, mDevice->getMetaState());
2637
2638 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, 0))
2639 << "Ignored device should return unknown key code state.";
2640 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 0))
2641 << "Ignored device should return unknown scan code state.";
2642 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 0))
2643 << "Ignored device should return unknown switch state.";
2644
2645 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B};
2646 uint8_t flags[2] = { 0, 1 };
2647 ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, keyCodes, flags))
2648 << "Ignored device should never mark any key codes.";
2649 ASSERT_EQ(0, flags[0]) << "Flag for unsupported key should be unchanged.";
2650 ASSERT_EQ(1, flags[1]) << "Flag for unsupported key should be unchanged.";
2651}
2652
2653TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRequestsToMappers) {
2654 // Configuration.
2655 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "key", "value");
2656
2657 FakeInputMapper& mapper1 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00002658 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2659 AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002660 mapper1.setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC);
2661 mapper1.setMetaState(AMETA_ALT_ON);
2662 mapper1.addSupportedKeyCode(AKEYCODE_A);
2663 mapper1.addSupportedKeyCode(AKEYCODE_B);
2664 mapper1.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
2665 mapper1.setKeyCodeState(AKEYCODE_B, AKEY_STATE_UP);
2666 mapper1.setScanCodeState(2, AKEY_STATE_DOWN);
2667 mapper1.setScanCodeState(3, AKEY_STATE_UP);
2668 mapper1.setSwitchState(4, AKEY_STATE_DOWN);
2669
2670 FakeInputMapper& mapper2 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00002671 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2672 AINPUT_SOURCE_TOUCHSCREEN);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002673 mapper2.setMetaState(AMETA_SHIFT_ON);
2674
2675 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002676 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002677
Harry Cuttsf13161a2023-03-08 14:15:49 +00002678 std::optional<std::string> propertyValue = mDevice->getConfiguration().getString("key");
2679 ASSERT_TRUE(propertyValue.has_value())
Michael Wrightd02c5b62014-02-10 15:10:22 -08002680 << "Device should have read configuration during configuration phase.";
Harry Cuttsf13161a2023-03-08 14:15:49 +00002681 ASSERT_EQ("value", *propertyValue);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002682
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002683 ASSERT_NO_FATAL_FAILURE(mapper1.assertConfigureWasCalled());
2684 ASSERT_NO_FATAL_FAILURE(mapper2.assertConfigureWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002685
2686 // Reset
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002687 unused += mDevice->reset(ARBITRARY_TIME);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002688 ASSERT_NO_FATAL_FAILURE(mapper1.assertResetWasCalled());
2689 ASSERT_NO_FATAL_FAILURE(mapper2.assertResetWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002690
2691 NotifyDeviceResetArgs resetArgs;
2692 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
2693 ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
2694 ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
2695
2696 // Metadata.
2697 ASSERT_FALSE(mDevice->isIgnored());
2698 ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), mDevice->getSources());
2699
Siarhei Vishniakou1983a712021-06-04 19:27:09 +00002700 InputDeviceInfo info = mDevice->getDeviceInfo();
Michael Wrightd02c5b62014-02-10 15:10:22 -08002701 ASSERT_EQ(DEVICE_ID, info.getId());
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002702 ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002703 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, info.getKeyboardType());
2704 ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), info.getSources());
2705
2706 // State queries.
2707 ASSERT_EQ(AMETA_ALT_ON | AMETA_SHIFT_ON, mDevice->getMetaState())
2708 << "Should query mappers and combine meta states.";
2709
2710 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2711 << "Should return unknown key code state when source not supported.";
2712 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2713 << "Should return unknown scan code state when source not supported.";
2714 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2715 << "Should return unknown switch state when source not supported.";
2716
2717 ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, AKEYCODE_A))
2718 << "Should query mapper when source is supported.";
2719 ASSERT_EQ(AKEY_STATE_UP, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 3))
2720 << "Should query mapper when source is supported.";
2721 ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 4))
2722 << "Should query mapper when source is supported.";
2723
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002724 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2};
Michael Wrightd02c5b62014-02-10 15:10:22 -08002725 uint8_t flags[4] = { 0, 0, 0, 1 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002726 ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -08002727 << "Should do nothing when source is unsupported.";
2728 ASSERT_EQ(0, flags[0]) << "Flag should be unchanged when source is unsupported.";
2729 ASSERT_EQ(0, flags[1]) << "Flag should be unchanged when source is unsupported.";
2730 ASSERT_EQ(0, flags[2]) << "Flag should be unchanged when source is unsupported.";
2731 ASSERT_EQ(1, flags[3]) << "Flag should be unchanged when source is unsupported.";
2732
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002733 ASSERT_TRUE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -08002734 << "Should query mapper when source is supported.";
2735 ASSERT_EQ(1, flags[0]) << "Flag for supported key should be set.";
2736 ASSERT_EQ(1, flags[1]) << "Flag for supported key should be set.";
2737 ASSERT_EQ(0, flags[2]) << "Flag for unsupported key should be unchanged.";
2738 ASSERT_EQ(1, flags[3]) << "Flag for unsupported key should be unchanged.";
2739
2740 // Event handling.
2741 RawEvent event;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002742 event.deviceId = EVENTHUB_ID;
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002743 unused += mDevice->process(&event, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002744
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002745 ASSERT_NO_FATAL_FAILURE(mapper1.assertProcessWasCalled());
2746 ASSERT_NO_FATAL_FAILURE(mapper2.assertProcessWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002747}
2748
Yeabkal Wubshitb1b96db2024-01-24 12:47:00 -08002749TEST_F(InputDeviceTest, Configure_SmoothScrollViewBehaviorNotSet) {
2750 // Set some behavior to force the configuration to be update.
2751 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "1");
2752 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2753 AINPUT_SOURCE_KEYBOARD);
2754
2755 std::list<NotifyArgs> unused =
2756 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2757 /*changes=*/{});
2758
2759 ASSERT_FALSE(mDevice->getDeviceInfo().getViewBehavior().shouldSmoothScroll.has_value());
2760}
2761
2762TEST_F(InputDeviceTest, Configure_SmoothScrollViewBehaviorEnabled) {
2763 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.viewBehavior_smoothScroll", "1");
2764 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2765 AINPUT_SOURCE_KEYBOARD);
2766
2767 std::list<NotifyArgs> unused =
2768 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2769 /*changes=*/{});
2770
2771 ASSERT_TRUE(mDevice->getDeviceInfo().getViewBehavior().shouldSmoothScroll.value_or(false));
2772}
2773
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -07002774TEST_F(InputDeviceTest, WakeDevice_AddsWakeFlagToProcessNotifyArgs) {
2775 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "1");
2776 FakeInputMapper& mapper =
2777 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2778 AINPUT_SOURCE_KEYBOARD);
2779 NotifyMotionArgs args1;
2780 NotifySwitchArgs args2;
2781 NotifyKeyArgs args3;
2782 mapper.setProcessResult({args1, args2, args3});
2783
2784 InputReaderConfiguration config;
2785 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2786
2787 RawEvent event;
2788 event.deviceId = EVENTHUB_ID;
2789 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2790
2791 for (auto& arg : notifyArgs) {
2792 if (const auto notifyMotionArgs = std::get_if<NotifyMotionArgs>(&arg)) {
2793 ASSERT_EQ(POLICY_FLAG_WAKE, notifyMotionArgs->policyFlags);
2794 } else if (const auto notifySwitchArgs = std::get_if<NotifySwitchArgs>(&arg)) {
2795 ASSERT_EQ(POLICY_FLAG_WAKE, notifySwitchArgs->policyFlags);
2796 } else if (const auto notifyKeyArgs = std::get_if<NotifyKeyArgs>(&arg)) {
2797 ASSERT_EQ(POLICY_FLAG_WAKE, notifyKeyArgs->policyFlags);
2798 }
2799 }
2800}
2801
2802TEST_F(InputDeviceTest, NotWakeDevice_DoesNotAddWakeFlagToProcessNotifyArgs) {
2803 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "0");
2804 FakeInputMapper& mapper =
2805 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2806 AINPUT_SOURCE_KEYBOARD);
2807 NotifyMotionArgs args;
2808 mapper.setProcessResult({args});
2809
2810 InputReaderConfiguration config;
2811 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2812
2813 RawEvent event;
2814 event.deviceId = EVENTHUB_ID;
2815 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2816
2817 // POLICY_FLAG_WAKE is not added to the NotifyArgs.
2818 ASSERT_EQ(0u, std::get<NotifyMotionArgs>(notifyArgs.front()).policyFlags);
2819}
2820
2821TEST_F(InputDeviceTest, NotWakeDevice_DoesNotRemoveExistingWakeFlagFromProcessNotifyArgs) {
2822 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "0");
2823 FakeInputMapper& mapper =
2824 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2825 AINPUT_SOURCE_KEYBOARD);
2826 NotifyMotionArgs args;
2827 args.policyFlags = POLICY_FLAG_WAKE;
2828 mapper.setProcessResult({args});
2829
2830 InputReaderConfiguration config;
2831 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2832
2833 RawEvent event;
2834 event.deviceId = EVENTHUB_ID;
2835 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2836
2837 // The POLICY_FLAG_WAKE is preserved, despite the device being a non-wake device.
2838 ASSERT_EQ(POLICY_FLAG_WAKE, std::get<NotifyMotionArgs>(notifyArgs.front()).policyFlags);
2839}
2840
Arthur Hung2c9a3342019-07-23 14:18:59 +08002841// A single input device is associated with a specific display. Check that:
2842// 1. Device is disabled if the viewport corresponding to the associated display is not found
Arpit Singh48189772023-05-30 14:12:49 +00002843// 2. Device is disabled when configure API is called
Arthur Hung2c9a3342019-07-23 14:18:59 +08002844TEST_F(InputDeviceTest, Configure_AssignsDisplayPort) {
Arpit Singh8e6fb252023-04-06 11:49:17 +00002845 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2846 AINPUT_SOURCE_TOUCHSCREEN);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002847
2848 // First Configuration.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002849 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002850 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2851 /*changes=*/{});
Arthur Hung2c9a3342019-07-23 14:18:59 +08002852
2853 // Device should be enabled by default.
2854 ASSERT_TRUE(mDevice->isEnabled());
2855
2856 // Prepare associated info.
2857 constexpr uint8_t hdmi = 1;
2858 const std::string UNIQUE_ID = "local:1";
2859
2860 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002861 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002862 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002863 // Device should be disabled because it is associated with a specific display via
2864 // input port <-> display port association, but the corresponding display is not found
2865 ASSERT_FALSE(mDevice->isEnabled());
2866
2867 // Prepare displays.
2868 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +00002869 ui::ROTATION_0, /*isActive=*/true, UNIQUE_ID, hdmi,
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00002870 ViewportType::INTERNAL);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002871 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002872 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002873 ASSERT_TRUE(mDevice->isEnabled());
2874
2875 // Device should be disabled after set disable.
2876 mFakePolicy->addDisabledDevice(mDevice->getId());
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002877 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002878 InputReaderConfiguration::Change::ENABLED_STATE);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002879 ASSERT_FALSE(mDevice->isEnabled());
2880
2881 // Device should still be disabled even found the associated display.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002882 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002883 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002884 ASSERT_FALSE(mDevice->isEnabled());
2885}
Michael Wrightd02c5b62014-02-10 15:10:22 -08002886
Christine Franks1ba71cc2021-04-07 14:37:42 -07002887TEST_F(InputDeviceTest, Configure_AssignsDisplayUniqueId) {
2888 // Device should be enabled by default.
2889 mFakePolicy->clearViewports();
Arpit Singh8e6fb252023-04-06 11:49:17 +00002890 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2891 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002892 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002893 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2894 /*changes=*/{});
Christine Franks1ba71cc2021-04-07 14:37:42 -07002895 ASSERT_TRUE(mDevice->isEnabled());
2896
2897 // Device should be disabled because it is associated with a specific display, but the
2898 // corresponding display is not found.
Christine Franks2a2293c2022-01-18 11:51:16 -08002899 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002900 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002901 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002902 ASSERT_FALSE(mDevice->isEnabled());
2903
2904 // Device should be enabled when a display is found.
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 Franks1ba71cc2021-04-07 14:37:42 -07002907 NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002908 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002909 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002910 ASSERT_TRUE(mDevice->isEnabled());
2911
2912 // Device should be disabled after set disable.
2913 mFakePolicy->addDisabledDevice(mDevice->getId());
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002914 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002915 InputReaderConfiguration::Change::ENABLED_STATE);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002916 ASSERT_FALSE(mDevice->isEnabled());
2917
2918 // Device should still be disabled even found the associated display.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002919 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002920 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002921 ASSERT_FALSE(mDevice->isEnabled());
2922}
2923
Christine Franks2a2293c2022-01-18 11:51:16 -08002924TEST_F(InputDeviceTest, Configure_UniqueId_CorrectlyMatches) {
2925 mFakePolicy->clearViewports();
Arpit Singh8e6fb252023-04-06 11:49:17 +00002926 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2927 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002928 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002929 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2930 /*changes=*/{});
Christine Franks2a2293c2022-01-18 11:51:16 -08002931
Christine Franks2a2293c2022-01-18 11:51:16 -08002932 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
2933 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00002934 ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
Christine Franks2a2293c2022-01-18 11:51:16 -08002935 NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan55c5ee22024-02-14 06:03:02 +00002936 const auto initialGeneration = mDevice->getGeneration();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002937 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002938 InputReaderConfiguration::Change::DISPLAY_INFO);
Antonio Kantek0ac5e092024-04-22 17:10:27 +00002939 ASSERT_EQ(DISPLAY_UNIQUE_ID, mDevice->getAssociatedDisplayUniqueIdByPort());
Prabir Pradhan55c5ee22024-02-14 06:03:02 +00002940 ASSERT_GT(mDevice->getGeneration(), initialGeneration);
2941 ASSERT_EQ(mDevice->getDeviceInfo().getAssociatedDisplayId(), SECONDARY_DISPLAY_ID);
Christine Franks2a2293c2022-01-18 11:51:16 -08002942}
2943
Siarhei Vishniakou30feb8c2022-09-28 10:48:29 -07002944/**
2945 * This test reproduces a crash caused by a dangling reference that remains after device is added
2946 * and removed. The reference is accessed in InputDevice::dump(..);
2947 */
2948TEST_F(InputDeviceTest, DumpDoesNotCrash) {
2949 constexpr int32_t TEST_EVENTHUB_ID = 10;
2950 mFakeEventHub->addDevice(TEST_EVENTHUB_ID, "Test EventHub device", InputDeviceClass::BATTERY);
2951
Harry Cutts33476232023-01-30 19:57:29 +00002952 InputDevice device(mReader->getContext(), /*id=*/1, /*generation=*/2, /*identifier=*/{});
Arpit Singh82f29a12023-06-13 15:05:53 +00002953 auto _ = device.addEventHubDevice(ARBITRARY_TIME, TEST_EVENTHUB_ID,
2954 mFakePolicy->getReaderConfiguration());
Siarhei Vishniakou30feb8c2022-09-28 10:48:29 -07002955 device.removeEventHubDevice(TEST_EVENTHUB_ID);
2956 std::string dumpStr, eventHubDevStr;
2957 device.dump(dumpStr, eventHubDevStr);
2958}
2959
Prabir Pradhanb54ffb22022-10-27 18:03:34 +00002960TEST_F(InputDeviceTest, GetBluetoothAddress) {
2961 const auto& address = mReader->getBluetoothAddress(DEVICE_ID);
2962 ASSERT_TRUE(address);
2963 ASSERT_EQ(DEVICE_BLUETOOTH_ADDRESS, *address);
2964}
2965
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002966TEST_F(InputDeviceTest, KernelBufferOverflowResetsMappers) {
2967 mFakePolicy->clearViewports();
2968 FakeInputMapper& mapper =
2969 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2970 AINPUT_SOURCE_KEYBOARD);
2971 std::list<NotifyArgs> unused =
2972 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2973 /*changes=*/{});
2974
2975 mapper.assertConfigureWasCalled();
2976 mapper.assertResetWasNotCalled();
2977
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -08002978 RawEvent event{.when = ARBITRARY_TIME,
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002979 .readTime = ARBITRARY_TIME,
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -08002980 .deviceId = EVENTHUB_ID,
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002981 .type = EV_SYN,
2982 .code = SYN_REPORT,
2983 .value = 0};
2984
2985 // Events are processed normally.
2986 unused = mDevice->process(&event, /*count=*/1);
2987 mapper.assertProcessWasCalled();
2988
2989 // Simulate a kernel buffer overflow, which generates a SYN_DROPPED event.
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002990 event.type = EV_SYN;
2991 event.code = SYN_DROPPED;
2992 event.value = 0;
2993 unused = mDevice->process(&event, /*count=*/1);
2994 mapper.assertProcessWasNotCalled();
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002995
2996 // All events until the next SYN_REPORT should be dropped.
2997 event.type = EV_KEY;
2998 event.code = KEY_A;
2999 event.value = 1;
3000 unused = mDevice->process(&event, /*count=*/1);
3001 mapper.assertProcessWasNotCalled();
3002
3003 // We get the SYN_REPORT event now, which is not forwarded to mappers.
Arpit Singh4b4a4572023-11-24 18:19:56 +00003004 // This should reset the mapper.
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003005 event.type = EV_SYN;
3006 event.code = SYN_REPORT;
3007 event.value = 0;
3008 unused = mDevice->process(&event, /*count=*/1);
3009 mapper.assertProcessWasNotCalled();
Arpit Singh4b4a4572023-11-24 18:19:56 +00003010 mapper.assertResetWasCalled();
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003011
3012 // The mapper receives events normally now.
3013 event.type = EV_KEY;
3014 event.code = KEY_B;
3015 event.value = 1;
3016 unused = mDevice->process(&event, /*count=*/1);
3017 mapper.assertProcessWasCalled();
3018}
3019
Chris Yef59a2f42020-10-16 12:55:26 -07003020// --- SensorInputMapperTest ---
3021
3022class SensorInputMapperTest : public InputMapperTest {
3023protected:
3024 static const int32_t ACCEL_RAW_MIN;
3025 static const int32_t ACCEL_RAW_MAX;
3026 static const int32_t ACCEL_RAW_FUZZ;
3027 static const int32_t ACCEL_RAW_FLAT;
3028 static const int32_t ACCEL_RAW_RESOLUTION;
3029
3030 static const int32_t GYRO_RAW_MIN;
3031 static const int32_t GYRO_RAW_MAX;
3032 static const int32_t GYRO_RAW_FUZZ;
3033 static const int32_t GYRO_RAW_FLAT;
3034 static const int32_t GYRO_RAW_RESOLUTION;
3035
3036 static const float GRAVITY_MS2_UNIT;
3037 static const float DEGREE_RADIAN_UNIT;
3038
3039 void prepareAccelAxes();
3040 void prepareGyroAxes();
3041 void setAccelProperties();
3042 void setGyroProperties();
3043 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::SENSOR); }
3044};
3045
3046const int32_t SensorInputMapperTest::ACCEL_RAW_MIN = -32768;
3047const int32_t SensorInputMapperTest::ACCEL_RAW_MAX = 32768;
3048const int32_t SensorInputMapperTest::ACCEL_RAW_FUZZ = 16;
3049const int32_t SensorInputMapperTest::ACCEL_RAW_FLAT = 0;
3050const int32_t SensorInputMapperTest::ACCEL_RAW_RESOLUTION = 8192;
3051
3052const int32_t SensorInputMapperTest::GYRO_RAW_MIN = -2097152;
3053const int32_t SensorInputMapperTest::GYRO_RAW_MAX = 2097152;
3054const int32_t SensorInputMapperTest::GYRO_RAW_FUZZ = 16;
3055const int32_t SensorInputMapperTest::GYRO_RAW_FLAT = 0;
3056const int32_t SensorInputMapperTest::GYRO_RAW_RESOLUTION = 1024;
3057
3058const float SensorInputMapperTest::GRAVITY_MS2_UNIT = 9.80665f;
3059const float SensorInputMapperTest::DEGREE_RADIAN_UNIT = 0.0174533f;
3060
3061void SensorInputMapperTest::prepareAccelAxes() {
3062 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3063 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3064 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3065 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3066 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Z, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3067 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3068}
3069
3070void SensorInputMapperTest::prepareGyroAxes() {
3071 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RX, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3072 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3073 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RY, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3074 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3075 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RZ, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3076 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3077}
3078
3079void SensorInputMapperTest::setAccelProperties() {
3080 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 0, InputDeviceSensorType::ACCELEROMETER,
3081 /* sensorDataIndex */ 0);
3082 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 1, InputDeviceSensorType::ACCELEROMETER,
3083 /* sensorDataIndex */ 1);
3084 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 2, InputDeviceSensorType::ACCELEROMETER,
3085 /* sensorDataIndex */ 2);
3086 mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP);
3087 addConfigurationProperty("sensor.accelerometer.reportingMode", "0");
3088 addConfigurationProperty("sensor.accelerometer.maxDelay", "100000");
3089 addConfigurationProperty("sensor.accelerometer.minDelay", "5000");
3090 addConfigurationProperty("sensor.accelerometer.power", "1.5");
3091}
3092
3093void SensorInputMapperTest::setGyroProperties() {
3094 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 3, InputDeviceSensorType::GYROSCOPE,
3095 /* sensorDataIndex */ 0);
3096 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 4, InputDeviceSensorType::GYROSCOPE,
3097 /* sensorDataIndex */ 1);
3098 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 5, InputDeviceSensorType::GYROSCOPE,
3099 /* sensorDataIndex */ 2);
3100 mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP);
3101 addConfigurationProperty("sensor.gyroscope.reportingMode", "0");
3102 addConfigurationProperty("sensor.gyroscope.maxDelay", "100000");
3103 addConfigurationProperty("sensor.gyroscope.minDelay", "5000");
3104 addConfigurationProperty("sensor.gyroscope.power", "0.8");
3105}
3106
3107TEST_F(SensorInputMapperTest, GetSources) {
Arpit Singhfb706c32023-04-26 15:07:55 +00003108 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003109
3110 ASSERT_EQ(static_cast<uint32_t>(AINPUT_SOURCE_SENSOR), mapper.getSources());
3111}
3112
3113TEST_F(SensorInputMapperTest, ProcessAccelerometerSensor) {
3114 setAccelProperties();
3115 prepareAccelAxes();
Arpit Singhfb706c32023-04-26 15:07:55 +00003116 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003117
3118 ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::ACCELEROMETER,
3119 std::chrono::microseconds(10000),
3120 std::chrono::microseconds(0)));
Chris Yee14523a2020-12-19 13:46:00 -08003121 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003122 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, 20000);
3123 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, -20000);
3124 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Z, 40000);
3125 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000);
3126 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Chris Yef59a2f42020-10-16 12:55:26 -07003127
3128 NotifySensorArgs args;
3129 std::vector<float> values = {20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT,
3130 -20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT,
3131 40000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT};
3132
3133 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args));
3134 ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR);
3135 ASSERT_EQ(args.deviceId, DEVICE_ID);
3136 ASSERT_EQ(args.sensorType, InputDeviceSensorType::ACCELEROMETER);
3137 ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH);
3138 ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME);
3139 ASSERT_EQ(args.values, values);
3140 mapper.flushSensor(InputDeviceSensorType::ACCELEROMETER);
3141}
3142
3143TEST_F(SensorInputMapperTest, ProcessGyroscopeSensor) {
3144 setGyroProperties();
3145 prepareGyroAxes();
Arpit Singhfb706c32023-04-26 15:07:55 +00003146 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003147
3148 ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::GYROSCOPE,
3149 std::chrono::microseconds(10000),
3150 std::chrono::microseconds(0)));
Chris Yee14523a2020-12-19 13:46:00 -08003151 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003152 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RX, 20000);
3153 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RY, -20000);
3154 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RZ, 40000);
3155 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000);
3156 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Chris Yef59a2f42020-10-16 12:55:26 -07003157
3158 NotifySensorArgs args;
3159 std::vector<float> values = {20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT,
3160 -20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT,
3161 40000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT};
3162
3163 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args));
3164 ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR);
3165 ASSERT_EQ(args.deviceId, DEVICE_ID);
3166 ASSERT_EQ(args.sensorType, InputDeviceSensorType::GYROSCOPE);
3167 ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH);
3168 ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME);
3169 ASSERT_EQ(args.values, values);
3170 mapper.flushSensor(InputDeviceSensorType::GYROSCOPE);
3171}
3172
Michael Wrightd02c5b62014-02-10 15:10:22 -08003173// --- KeyboardInputMapperTest ---
3174
3175class KeyboardInputMapperTest : public InputMapperTest {
3176protected:
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003177 void SetUp() override {
3178 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
3179 InputDeviceClass::ALPHAKEY);
3180 }
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003181 const std::string UNIQUE_ID = "local:0";
Zixuan Qufecb6062022-11-12 04:44:31 +00003182 const KeyboardLayoutInfo DEVICE_KEYBOARD_LAYOUT_INFO = KeyboardLayoutInfo("en-US", "qwerty");
Michael Wrighta9cf4192022-12-01 23:46:39 +00003183 void prepareDisplay(ui::Rotation orientation);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003184
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003185 void testDPadKeyRotation(KeyboardInputMapper& mapper, int32_t originalScanCode,
Arthur Hung2c9a3342019-07-23 14:18:59 +08003186 int32_t originalKeyCode, int32_t rotatedKeyCode,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003187 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003188};
3189
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003190/* Similar to setDisplayInfoAndReconfigure, but pre-populates all parameters except for the
3191 * orientation.
3192 */
Michael Wrighta9cf4192022-12-01 23:46:39 +00003193void KeyboardInputMapperTest::prepareDisplay(ui::Rotation orientation) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003194 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
3195 NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003196}
3197
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003198void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper& mapper,
Arthur Hung2c9a3342019-07-23 14:18:59 +08003199 int32_t originalScanCode, int32_t originalKeyCode,
Linnan Li13bf76a2024-05-05 19:18:02 +08003200 int32_t rotatedKeyCode,
3201 ui::LogicalDisplayId displayId) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003202 NotifyKeyArgs args;
3203
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003204 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003205 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3206 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3207 ASSERT_EQ(originalScanCode, args.scanCode);
3208 ASSERT_EQ(rotatedKeyCode, args.keyCode);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003209 ASSERT_EQ(displayId, args.displayId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003210
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003211 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003212 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3213 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3214 ASSERT_EQ(originalScanCode, args.scanCode);
3215 ASSERT_EQ(rotatedKeyCode, args.keyCode);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003216 ASSERT_EQ(displayId, args.displayId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003217}
3218
Michael Wrightd02c5b62014-02-10 15:10:22 -08003219TEST_F(KeyboardInputMapperTest, GetSources) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003220 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003221 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003222
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003223 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003224}
3225
3226TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) {
3227 const int32_t USAGE_A = 0x070004;
3228 const int32_t USAGE_UNKNOWN = 0x07ffff;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003229 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3230 mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
Chris Yea52ade12020-08-27 16:49:20 -07003231 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, POLICY_FLAG_WAKE);
3232 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, POLICY_FLAG_WAKE);
3233 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, POLICY_FLAG_WAKE);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003234
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003235 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003236 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003237 // Initial metastate is AMETA_NONE.
3238 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003239
3240 // Key down by scan code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003241 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003242 NotifyKeyArgs args;
3243 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3244 ASSERT_EQ(DEVICE_ID, args.deviceId);
3245 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3246 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3247 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3248 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3249 ASSERT_EQ(KEY_HOME, args.scanCode);
3250 ASSERT_EQ(AMETA_NONE, args.metaState);
3251 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3252 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3253 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3254
3255 // Key up by scan code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003256 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003257 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3258 ASSERT_EQ(DEVICE_ID, args.deviceId);
3259 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3260 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3261 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3262 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3263 ASSERT_EQ(KEY_HOME, args.scanCode);
3264 ASSERT_EQ(AMETA_NONE, args.metaState);
3265 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3266 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3267 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3268
3269 // Key down by usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003270 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A);
3271 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, 0, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003272 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3273 ASSERT_EQ(DEVICE_ID, args.deviceId);
3274 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3275 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3276 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3277 ASSERT_EQ(AKEYCODE_A, args.keyCode);
3278 ASSERT_EQ(0, args.scanCode);
3279 ASSERT_EQ(AMETA_NONE, args.metaState);
3280 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3281 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3282 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3283
3284 // Key up by usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003285 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A);
3286 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003287 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3288 ASSERT_EQ(DEVICE_ID, args.deviceId);
3289 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3290 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3291 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3292 ASSERT_EQ(AKEYCODE_A, args.keyCode);
3293 ASSERT_EQ(0, args.scanCode);
3294 ASSERT_EQ(AMETA_NONE, args.metaState);
3295 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3296 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3297 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3298
3299 // Key down with unknown scan code or usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003300 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
3301 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003302 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3303 ASSERT_EQ(DEVICE_ID, args.deviceId);
3304 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3305 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3306 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3307 ASSERT_EQ(0, args.keyCode);
3308 ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
3309 ASSERT_EQ(AMETA_NONE, args.metaState);
3310 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3311 ASSERT_EQ(0U, args.policyFlags);
3312 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3313
3314 // Key up with unknown scan code or usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003315 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
3316 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_UNKNOWN, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003317 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3318 ASSERT_EQ(DEVICE_ID, args.deviceId);
3319 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3320 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3321 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3322 ASSERT_EQ(0, args.keyCode);
3323 ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
3324 ASSERT_EQ(AMETA_NONE, args.metaState);
3325 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3326 ASSERT_EQ(0U, args.policyFlags);
3327 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3328}
3329
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003330TEST_F(KeyboardInputMapperTest, Process_KeyRemapping) {
3331 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
3332 mFakeEventHub->addKey(EVENTHUB_ID, KEY_B, 0, AKEYCODE_B, 0);
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003333
3334 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003335 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003336
Linnan Lie5657f22024-09-13 21:54:37 +08003337 mFakeEventHub->setKeyRemapping(EVENTHUB_ID, {{AKEYCODE_A, AKEYCODE_B}});
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003338 // Key down by scan code.
3339 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_A, 1);
3340 NotifyKeyArgs args;
3341 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3342 ASSERT_EQ(AKEYCODE_B, args.keyCode);
3343
3344 // Key up by scan code.
3345 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 0);
3346 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3347 ASSERT_EQ(AKEYCODE_B, args.keyCode);
3348}
3349
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003350/**
3351 * Ensure that the readTime is set to the time when the EV_KEY is received.
3352 */
3353TEST_F(KeyboardInputMapperTest, Process_SendsReadTime) {
3354 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3355
3356 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003357 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003358 NotifyKeyArgs args;
3359
3360 // Key down
Harry Cutts33476232023-01-30 19:57:29 +00003361 process(mapper, ARBITRARY_TIME, /*readTime=*/12, EV_KEY, KEY_HOME, 1);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003362 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3363 ASSERT_EQ(12, args.readTime);
3364
3365 // Key up
Harry Cutts33476232023-01-30 19:57:29 +00003366 process(mapper, ARBITRARY_TIME, /*readTime=*/15, EV_KEY, KEY_HOME, 1);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003367 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3368 ASSERT_EQ(15, args.readTime);
3369}
3370
Michael Wrightd02c5b62014-02-10 15:10:22 -08003371TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003372 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFTSHIFT, 0, AKEYCODE_SHIFT_LEFT, 0);
3373 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
Chris Yea52ade12020-08-27 16:49:20 -07003374 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 0);
3375 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0);
3376 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003377
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003378 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003379 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003380
Arthur Hung95f68612022-04-07 14:08:22 +08003381 // Initial metastate is AMETA_NONE.
3382 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003383
3384 // Metakey down.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003385 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003386 NotifyKeyArgs args;
3387 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3388 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003389 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
arthurhungdcef2dc2020-08-11 14:47:50 +08003390 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003391
3392 // Key down.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003393 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003394 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3395 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003396 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003397
3398 // Key up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003399 process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_KEY, KEY_A, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003400 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3401 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003402 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003403
3404 // Metakey up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003405 process(mapper, ARBITRARY_TIME + 3, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003406 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3407 ASSERT_EQ(AMETA_NONE, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003408 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
arthurhungdcef2dc2020-08-11 14:47:50 +08003409 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003410}
3411
3412TEST_F(KeyboardInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateDPad) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003413 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3414 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3415 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3416 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003417
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003418 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003419 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003420
Michael Wrighta9cf4192022-12-01 23:46:39 +00003421 prepareDisplay(ui::ROTATION_90);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003422 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3423 KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
3424 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3425 KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
3426 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3427 KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
3428 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3429 KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
3430}
3431
3432TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003433 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3434 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3435 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3436 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003437
Michael Wrightd02c5b62014-02-10 15:10:22 -08003438 addConfigurationProperty("keyboard.orientationAware", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003439 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003440 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003441
Michael Wrighta9cf4192022-12-01 23:46:39 +00003442 prepareDisplay(ui::ROTATION_0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003443 ASSERT_NO_FATAL_FAILURE(
3444 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
3445 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3446 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3447 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3448 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3449 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3450 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003451
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003452 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003453 prepareDisplay(ui::ROTATION_90);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003454 ASSERT_NO_FATAL_FAILURE(
3455 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3456 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3457 AKEYCODE_DPAD_UP, DISPLAY_ID));
3458 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3459 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3460 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3461 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003462
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003463 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003464 prepareDisplay(ui::ROTATION_180);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003465 ASSERT_NO_FATAL_FAILURE(
3466 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3467 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3468 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3469 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3470 AKEYCODE_DPAD_UP, DISPLAY_ID));
3471 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3472 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003473
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003474 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003475 prepareDisplay(ui::ROTATION_270);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003476 ASSERT_NO_FATAL_FAILURE(
3477 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3478 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3479 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3480 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3481 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3482 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3483 AKEYCODE_DPAD_UP, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003484
3485 // Special case: if orientation changes while key is down, we still emit the same keycode
3486 // in the key up as we did in the key down.
3487 NotifyKeyArgs args;
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003488 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003489 prepareDisplay(ui::ROTATION_270);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003490 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003491 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3492 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3493 ASSERT_EQ(KEY_UP, args.scanCode);
3494 ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
3495
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003496 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003497 prepareDisplay(ui::ROTATION_180);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003498 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003499 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3500 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3501 ASSERT_EQ(KEY_UP, args.scanCode);
3502 ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
3503}
3504
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003505TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_NotOrientationAware) {
3506 // If the keyboard is not orientation aware,
3507 // key events should not be associated with a specific display id
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003508 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003509
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003510 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003511 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003512 NotifyKeyArgs args;
3513
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003514 // Display id should be LogicalDisplayId::INVALID without any display configuration.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003515 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003516 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003517 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003518 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003519 ASSERT_EQ(ui::LogicalDisplayId::INVALID, args.displayId);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003520
Michael Wrighta9cf4192022-12-01 23:46:39 +00003521 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003522 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003523 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003524 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003525 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003526 ASSERT_EQ(ui::LogicalDisplayId::INVALID, args.displayId);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003527}
3528
3529TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_OrientationAware) {
3530 // If the keyboard is orientation aware,
3531 // key events should be associated with the internal viewport
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003532 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003533
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003534 addConfigurationProperty("keyboard.orientationAware", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003535 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003536 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003537 NotifyKeyArgs args;
3538
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003539 // Display id should be LogicalDisplayId::INVALID without any display configuration.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003540 // ^--- already checked by the previous test
3541
Michael Wrighta9cf4192022-12-01 23:46:39 +00003542 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003543 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003544 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003545 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003546 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003547 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3548 ASSERT_EQ(DISPLAY_ID, args.displayId);
3549
Linnan Li13bf76a2024-05-05 19:18:02 +08003550 constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003551 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003552 setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003553 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003554 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003555 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003556 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003557 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3558 ASSERT_EQ(newDisplayId, args.displayId);
3559}
3560
Michael Wrightd02c5b62014-02-10 15:10:22 -08003561TEST_F(KeyboardInputMapperTest, GetKeyCodeState) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003562 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003563 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003564
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003565 mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003566 ASSERT_EQ(1, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003567
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003568 mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003569 ASSERT_EQ(0, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003570}
3571
Philip Junker4af3b3d2021-12-14 10:36:55 +01003572TEST_F(KeyboardInputMapperTest, GetKeyCodeForKeyLocation) {
3573 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003574 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Philip Junker4af3b3d2021-12-14 10:36:55 +01003575
3576 mFakeEventHub->addKeyCodeMapping(EVENTHUB_ID, AKEYCODE_Y, AKEYCODE_Z);
3577 ASSERT_EQ(AKEYCODE_Z, mapper.getKeyCodeForKeyLocation(AKEYCODE_Y))
3578 << "If a mapping is available, the result is equal to the mapping";
3579
3580 ASSERT_EQ(AKEYCODE_A, mapper.getKeyCodeForKeyLocation(AKEYCODE_A))
3581 << "If no mapping is available, the result is the key location";
3582}
3583
Michael Wrightd02c5b62014-02-10 15:10:22 -08003584TEST_F(KeyboardInputMapperTest, GetScanCodeState) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003585 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003586 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003587
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003588 mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003589 ASSERT_EQ(1, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003590
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003591 mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003592 ASSERT_EQ(0, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003593}
3594
3595TEST_F(KeyboardInputMapperTest, MarkSupportedKeyCodes) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003596 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003597 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003598
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003599 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003600
Michael Wrightd02c5b62014-02-10 15:10:22 -08003601 uint8_t flags[2] = { 0, 0 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07003602 ASSERT_TRUE(mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_A, AKEYCODE_B}, flags));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003603 ASSERT_TRUE(flags[0]);
3604 ASSERT_FALSE(flags[1]);
3605}
3606
3607TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003608 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3609 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3610 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3611 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3612 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3613 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003614
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003615 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003616 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003617 // Initial metastate is AMETA_NONE.
3618 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003619
3620 // Initialization should have turned all of the lights off.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003621 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3622 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3623 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003624
3625 // Toggle caps lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003626 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3627 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003628 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3629 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3630 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003631 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003632
3633 // Toggle num lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003634 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3635 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003636 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3637 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3638 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003639 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003640
3641 // Toggle caps lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003642 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3643 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003644 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3645 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3646 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003647 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003648
3649 // Toggle scroll lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003650 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3651 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003652 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3653 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3654 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003655 ASSERT_EQ(AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003656
3657 // Toggle num lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003658 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3659 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003660 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3661 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3662 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003663 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003664
3665 // Toggle scroll lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003666 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3667 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003668 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3669 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3670 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003671 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003672}
3673
Chris Yea52ade12020-08-27 16:49:20 -07003674TEST_F(KeyboardInputMapperTest, NoMetaStateWhenMetaKeysNotPresent) {
3675 mFakeEventHub->addKey(EVENTHUB_ID, BTN_A, 0, AKEYCODE_BUTTON_A, 0);
3676 mFakeEventHub->addKey(EVENTHUB_ID, BTN_B, 0, AKEYCODE_BUTTON_B, 0);
3677 mFakeEventHub->addKey(EVENTHUB_ID, BTN_X, 0, AKEYCODE_BUTTON_X, 0);
3678 mFakeEventHub->addKey(EVENTHUB_ID, BTN_Y, 0, AKEYCODE_BUTTON_Y, 0);
3679
3680 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003681 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Chris Yea52ade12020-08-27 16:49:20 -07003682
Chris Yea52ade12020-08-27 16:49:20 -07003683 // Meta state should be AMETA_NONE after reset
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003684 std::list<NotifyArgs> unused = mapper.reset(ARBITRARY_TIME);
Chris Yea52ade12020-08-27 16:49:20 -07003685 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3686 // Meta state should be AMETA_NONE with update, as device doesn't have the keys.
3687 mapper.updateMetaState(AKEYCODE_NUM_LOCK);
3688 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3689
3690 NotifyKeyArgs args;
3691 // Press button "A"
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003692 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_A, 1);
Chris Yea52ade12020-08-27 16:49:20 -07003693 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3694 ASSERT_EQ(AMETA_NONE, args.metaState);
3695 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3696 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3697 ASSERT_EQ(AKEYCODE_BUTTON_A, args.keyCode);
3698
3699 // Button up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003700 process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_KEY, BTN_A, 0);
Chris Yea52ade12020-08-27 16:49:20 -07003701 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3702 ASSERT_EQ(AMETA_NONE, args.metaState);
3703 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3704 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3705 ASSERT_EQ(AKEYCODE_BUTTON_A, args.keyCode);
3706}
3707
Arthur Hung2c9a3342019-07-23 14:18:59 +08003708TEST_F(KeyboardInputMapperTest, Configure_AssignsDisplayPort) {
3709 // keyboard 1.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003710 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3711 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3712 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3713 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003714
3715 // keyboard 2.
3716 const std::string USB2 = "USB2";
arthurhungdcef2dc2020-08-11 14:47:50 +08003717 const std::string DEVICE_NAME2 = "KEYBOARD2";
Arthur Hung2c9a3342019-07-23 14:18:59 +08003718 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003719 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
arthurhungdcef2dc2020-08-11 14:47:50 +08003720 std::shared_ptr<InputDevice> device2 =
3721 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
Dominik Laskowski2f01d772022-03-23 16:01:29 -07003722 ftl::Flags<InputDeviceClass>(0));
arthurhungdcef2dc2020-08-11 14:47:50 +08003723
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003724 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3725 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3726 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3727 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003728
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003729 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003730 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003731
Arpit Singh67ca6842023-04-26 14:43:16 +00003732 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003733 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003734 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3735 mFakePolicy
3736 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003737 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003738 std::list<NotifyArgs> unused =
3739 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003740 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003741 unused += device2->reset(ARBITRARY_TIME);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003742
3743 // Prepared displays and associated info.
3744 constexpr uint8_t hdmi1 = 0;
3745 constexpr uint8_t hdmi2 = 1;
3746 const std::string SECONDARY_UNIQUE_ID = "local:1";
3747
3748 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
3749 mFakePolicy->addInputPortAssociation(USB2, hdmi2);
3750
3751 // No associated display viewport found, should disable the device.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003752 unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003753 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003754 ASSERT_FALSE(device2->isEnabled());
3755
3756 // Prepare second display.
Linnan Li13bf76a2024-05-05 19:18:02 +08003757 constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
Michael Wrighta9cf4192022-12-01 23:46:39 +00003758 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003759 UNIQUE_ID, hdmi1, ViewportType::INTERNAL);
Michael Wrighta9cf4192022-12-01 23:46:39 +00003760 setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003761 SECONDARY_UNIQUE_ID, hdmi2, ViewportType::EXTERNAL);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003762 // Default device will reconfigure above, need additional reconfiguration for another device.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003763 unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003764 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003765
3766 // Device should be enabled after the associated display is found.
3767 ASSERT_TRUE(mDevice->isEnabled());
3768 ASSERT_TRUE(device2->isEnabled());
3769
3770 // Test pad key events
3771 ASSERT_NO_FATAL_FAILURE(
3772 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
3773 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3774 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3775 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3776 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3777 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3778 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3779
3780 ASSERT_NO_FATAL_FAILURE(
3781 testDPadKeyRotation(mapper2, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, newDisplayId));
3782 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3783 AKEYCODE_DPAD_RIGHT, newDisplayId));
3784 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3785 AKEYCODE_DPAD_DOWN, newDisplayId));
3786 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3787 AKEYCODE_DPAD_LEFT, newDisplayId));
3788}
Michael Wrightd02c5b62014-02-10 15:10:22 -08003789
arthurhungc903df12020-08-11 15:08:42 +08003790TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleAfterReattach) {
3791 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3792 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3793 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3794 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3795 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3796 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3797
3798 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003799 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003800 // Initial metastate is AMETA_NONE.
3801 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
arthurhungc903df12020-08-11 15:08:42 +08003802
3803 // Initialization should have turned all of the lights off.
3804 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3805 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3806 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3807
3808 // Toggle caps lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003809 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3810 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003811 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3812 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
3813
3814 // Toggle num lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003815 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3816 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003817 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3818 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
3819
3820 // Toggle scroll lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003821 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3822 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003823 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3824 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
3825
3826 mFakeEventHub->removeDevice(EVENTHUB_ID);
3827 mReader->loopOnce();
3828
3829 // keyboard 2 should default toggle keys.
3830 const std::string USB2 = "USB2";
3831 const std::string DEVICE_NAME2 = "KEYBOARD2";
3832 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
3833 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
3834 std::shared_ptr<InputDevice> device2 =
3835 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
Dominik Laskowski2f01d772022-03-23 16:01:29 -07003836 ftl::Flags<InputDeviceClass>(0));
arthurhungc903df12020-08-11 15:08:42 +08003837 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3838 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
3839 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3840 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3841 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3842 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3843
Arpit Singh67ca6842023-04-26 14:43:16 +00003844 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
arthurhung6fe95782020-10-05 22:41:16 +08003845 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003846 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3847 mFakePolicy
3848 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003849 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003850 std::list<NotifyArgs> unused =
3851 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003852 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003853 unused += device2->reset(ARBITRARY_TIME);
arthurhungc903df12020-08-11 15:08:42 +08003854
3855 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_CAPSL));
3856 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_NUML));
3857 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_SCROLLL));
arthurhung6fe95782020-10-05 22:41:16 +08003858 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON,
3859 mapper2.getMetaState());
arthurhungc903df12020-08-11 15:08:42 +08003860}
3861
Arthur Hungcb40a002021-08-03 14:31:01 +00003862TEST_F(KeyboardInputMapperTest, Process_toggleCapsLockState) {
3863 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3864 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3865 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3866
3867 // Suppose we have two mappers. (DPAD + KEYBOARD)
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003868 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD);
Arthur Hungcb40a002021-08-03 14:31:01 +00003869 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003870 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003871 // Initial metastate is AMETA_NONE.
3872 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Arthur Hungcb40a002021-08-03 14:31:01 +00003873
3874 mReader->toggleCapsLockState(DEVICE_ID);
3875 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
3876}
3877
Arthur Hungfb3cc112022-04-13 07:39:50 +00003878TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleInMultiDevices) {
3879 // keyboard 1.
3880 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3881 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3882 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3883 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3884 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3885 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3886
3887 KeyboardInputMapper& mapper1 =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003888 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hungfb3cc112022-04-13 07:39:50 +00003889
3890 // keyboard 2.
3891 const std::string USB2 = "USB2";
3892 const std::string DEVICE_NAME2 = "KEYBOARD2";
3893 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
3894 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
3895 std::shared_ptr<InputDevice> device2 =
3896 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
3897 ftl::Flags<InputDeviceClass>(0));
3898 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3899 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
3900 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3901 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3902 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3903 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3904
Arpit Singh67ca6842023-04-26 14:43:16 +00003905 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
Arthur Hungfb3cc112022-04-13 07:39:50 +00003906 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003907 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3908 mFakePolicy
3909 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003910 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003911 std::list<NotifyArgs> unused =
3912 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003913 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003914 unused += device2->reset(ARBITRARY_TIME);
Arthur Hungfb3cc112022-04-13 07:39:50 +00003915
Arthur Hung95f68612022-04-07 14:08:22 +08003916 // Initial metastate is AMETA_NONE.
3917 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
3918 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
3919
3920 // Toggle num lock on and off.
3921 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3922 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Arthur Hungfb3cc112022-04-13 07:39:50 +00003923 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3924 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper1.getMetaState());
3925 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper2.getMetaState());
3926
3927 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3928 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
3929 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3930 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
3931 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
3932
3933 // Toggle caps lock on and off.
3934 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3935 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
3936 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3937 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper1.getMetaState());
3938 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper2.getMetaState());
3939
3940 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3941 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
3942 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3943 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
3944 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
3945
3946 // Toggle scroll lock on and off.
3947 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3948 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
3949 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3950 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper1.getMetaState());
3951 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper2.getMetaState());
3952
3953 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3954 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
3955 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3956 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
3957 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
3958}
3959
Arthur Hung2141d542022-08-23 07:45:21 +00003960TEST_F(KeyboardInputMapperTest, Process_DisabledDevice) {
3961 const int32_t USAGE_A = 0x070004;
3962 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3963 mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
3964
3965 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003966 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung2141d542022-08-23 07:45:21 +00003967 // Key down by scan code.
3968 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
3969 NotifyKeyArgs args;
3970 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3971 ASSERT_EQ(DEVICE_ID, args.deviceId);
3972 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3973 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3974 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3975 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3976 ASSERT_EQ(KEY_HOME, args.scanCode);
3977 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3978
3979 // Disable device, it should synthesize cancellation events for down events.
3980 mFakePolicy->addDisabledDevice(DEVICE_ID);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003981 configureDevice(InputReaderConfiguration::Change::ENABLED_STATE);
Arthur Hung2141d542022-08-23 07:45:21 +00003982
3983 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3984 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3985 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3986 ASSERT_EQ(KEY_HOME, args.scanCode);
3987 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_CANCELED, args.flags);
3988}
3989
Zixuan Qufecb6062022-11-12 04:44:31 +00003990TEST_F(KeyboardInputMapperTest, Configure_AssignKeyboardLayoutInfo) {
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003991 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Zixuan Qufecb6062022-11-12 04:44:31 +00003992 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003993 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
3994 /*changes=*/{});
Zixuan Qufecb6062022-11-12 04:44:31 +00003995
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +00003996 uint32_t generation = mReader->getContext()->getGeneration();
Zixuan Qufecb6062022-11-12 04:44:31 +00003997 mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
3998
3999 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004000 InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
Zixuan Qufecb6062022-11-12 04:44:31 +00004001
4002 InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
4003 ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.languageTag,
4004 deviceInfo.getKeyboardLayoutInfo()->languageTag);
4005 ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.layoutType,
4006 deviceInfo.getKeyboardLayoutInfo()->layoutType);
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +00004007 ASSERT_TRUE(mReader->getContext()->getGeneration() != generation);
4008
4009 // Call change layout association with the same values: Generation shouldn't change
4010 generation = mReader->getContext()->getGeneration();
4011 mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
4012 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
4013 InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
4014 ASSERT_TRUE(mReader->getContext()->getGeneration() == generation);
Zixuan Qufecb6062022-11-12 04:44:31 +00004015}
4016
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004017TEST_F(KeyboardInputMapperTest, LayoutInfoCorrectlyMapped) {
4018 mFakeEventHub->setRawLayoutInfo(EVENTHUB_ID,
4019 RawLayoutInfo{.languageTag = "en", .layoutType = "extended"});
4020
4021 // Configuration
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004022 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004023 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004024 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004025
4026 ASSERT_EQ("en", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->languageTag);
4027 ASSERT_EQ("extended", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->layoutType);
4028}
4029
Justin Chung71ddb432023-03-27 04:29:07 +00004030TEST_F(KeyboardInputMapperTest, Process_GesureEventToSetFlagKeepTouchMode) {
4031 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, POLICY_FLAG_GESTURE);
4032 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004033 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Justin Chung71ddb432023-03-27 04:29:07 +00004034 NotifyKeyArgs args;
4035
4036 // Key down
4037 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFT, 1);
4038 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4039 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_KEEP_TOUCH_MODE, args.flags);
4040}
4041
Prabir Pradhan38636652024-07-23 21:59:36 +00004042/**
4043 * When there is more than one KeyboardInputMapper for an InputDevice, each mapper should produce
4044 * events that use the shared keyboard source across all mappers. This is to ensure that each
4045 * input device generates key events in a consistent manner, regardless of which mapper produces
4046 * the event.
4047 */
4048TEST_F(KeyboardInputMapperTest, UsesSharedKeyboardSource) {
4049 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4050
4051 // Add a mapper with SOURCE_KEYBOARD
4052 KeyboardInputMapper& keyboardMapper =
4053 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
4054
4055 process(keyboardMapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1);
4056 ASSERT_NO_FATAL_FAILURE(
4057 mFakeListener->assertNotifyKeyWasCalled(WithSource(AINPUT_SOURCE_KEYBOARD)));
4058 process(keyboardMapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0);
4059 ASSERT_NO_FATAL_FAILURE(
4060 mFakeListener->assertNotifyKeyWasCalled(WithSource(AINPUT_SOURCE_KEYBOARD)));
4061
4062 // Add a mapper with SOURCE_DPAD
4063 KeyboardInputMapper& dpadMapper =
4064 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD);
4065 for (auto* mapper : {&keyboardMapper, &dpadMapper}) {
4066 process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1);
4067 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
4068 WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD)));
4069 process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0);
4070 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
4071 WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD)));
4072 }
4073
4074 // Add a mapper with SOURCE_GAMEPAD
4075 KeyboardInputMapper& gamepadMapper =
4076 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_GAMEPAD);
4077 for (auto* mapper : {&keyboardMapper, &dpadMapper, &gamepadMapper}) {
4078 process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1);
4079 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
4080 WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD)));
4081 process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0);
4082 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
4083 WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD)));
4084 }
4085}
4086
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004087// --- KeyboardInputMapperTest_ExternalAlphabeticDevice ---
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004088
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004089class KeyboardInputMapperTest_ExternalAlphabeticDevice : public InputMapperTest {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004090protected:
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004091 void SetUp() override {
4092 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
4093 InputDeviceClass::ALPHAKEY | InputDeviceClass::EXTERNAL);
4094 }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004095};
4096
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004097// --- KeyboardInputMapperTest_ExternalNonAlphabeticDevice ---
4098
4099class KeyboardInputMapperTest_ExternalNonAlphabeticDevice : public InputMapperTest {
4100protected:
4101 void SetUp() override {
4102 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
4103 InputDeviceClass::EXTERNAL);
4104 }
4105};
4106
4107TEST_F(KeyboardInputMapperTest_ExternalAlphabeticDevice, WakeBehavior_AlphabeticKeyboard) {
Vaibhav Devmurari16257862023-03-06 10:06:32 +00004108 // For external devices, keys will trigger wake on key down. Media keys should also trigger
4109 // wake if triggered from external devices.
Powei Fengd041c5d2019-05-03 17:11:33 -07004110
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004111 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, 0);
4112 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
4113 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
4114 POLICY_FLAG_WAKE);
Powei Fengd041c5d2019-05-03 17:11:33 -07004115
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004116 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004117 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Powei Fengd041c5d2019-05-03 17:11:33 -07004118
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004119 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004120 NotifyKeyArgs args;
4121 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4122 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4123
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004124 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004125 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4126 ASSERT_EQ(uint32_t(0), args.policyFlags);
4127
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004128 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004129 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Vaibhav Devmurari16257862023-03-06 10:06:32 +00004130 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
Powei Fengd041c5d2019-05-03 17:11:33 -07004131
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004132 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004133 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4134 ASSERT_EQ(uint32_t(0), args.policyFlags);
4135
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004136 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004137 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4138 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4139
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004140 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004141 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4142 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4143}
4144
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004145TEST_F(KeyboardInputMapperTest_ExternalNonAlphabeticDevice, WakeBehavior_NonAlphabeticKeyboard) {
Vaibhav Devmurari2681a812024-01-11 00:15:35 +00004146 // For external devices, keys will trigger wake on key down. Media keys should not trigger
4147 // wake if triggered from external non-alphaebtic keyboard (e.g. headsets).
4148
4149 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
4150 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
4151 POLICY_FLAG_WAKE);
4152
4153 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004154 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmurari2681a812024-01-11 00:15:35 +00004155
4156 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
4157 NotifyKeyArgs args;
4158 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4159 ASSERT_EQ(uint32_t(0), args.policyFlags);
4160
4161 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
4162 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4163 ASSERT_EQ(uint32_t(0), args.policyFlags);
4164
4165 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1);
4166 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4167 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4168
4169 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0);
4170 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4171 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4172}
4173
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004174TEST_F(KeyboardInputMapperTest_ExternalAlphabeticDevice, DoNotWakeByDefaultBehavior) {
Powei Fengd041c5d2019-05-03 17:11:33 -07004175 // Tv Remote key's wake behavior is prescribed by the keylayout file.
Powei Fengd041c5d2019-05-03 17:11:33 -07004176
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004177 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4178 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
4179 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, POLICY_FLAG_WAKE);
Powei Fengd041c5d2019-05-03 17:11:33 -07004180
Powei Fengd041c5d2019-05-03 17:11:33 -07004181 addConfigurationProperty("keyboard.doNotWakeByDefault", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004182 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004183 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Powei Fengd041c5d2019-05-03 17:11:33 -07004184
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004185 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004186 NotifyKeyArgs args;
4187 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4188 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4189
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004190 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004191 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4192 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4193
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004194 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_DOWN, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004195 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4196 ASSERT_EQ(uint32_t(0), args.policyFlags);
4197
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004198 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_DOWN, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004199 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4200 ASSERT_EQ(uint32_t(0), args.policyFlags);
4201
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004202 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004203 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4204 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4205
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004206 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004207 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4208 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4209}
4210
Michael Wrightd02c5b62014-02-10 15:10:22 -08004211// --- TouchInputMapperTest ---
4212
4213class TouchInputMapperTest : public InputMapperTest {
4214protected:
4215 static const int32_t RAW_X_MIN;
4216 static const int32_t RAW_X_MAX;
4217 static const int32_t RAW_Y_MIN;
4218 static const int32_t RAW_Y_MAX;
4219 static const int32_t RAW_TOUCH_MIN;
4220 static const int32_t RAW_TOUCH_MAX;
4221 static const int32_t RAW_TOOL_MIN;
4222 static const int32_t RAW_TOOL_MAX;
4223 static const int32_t RAW_PRESSURE_MIN;
4224 static const int32_t RAW_PRESSURE_MAX;
4225 static const int32_t RAW_ORIENTATION_MIN;
4226 static const int32_t RAW_ORIENTATION_MAX;
4227 static const int32_t RAW_DISTANCE_MIN;
4228 static const int32_t RAW_DISTANCE_MAX;
4229 static const int32_t RAW_TILT_MIN;
4230 static const int32_t RAW_TILT_MAX;
4231 static const int32_t RAW_ID_MIN;
4232 static const int32_t RAW_ID_MAX;
4233 static const int32_t RAW_SLOT_MIN;
4234 static const int32_t RAW_SLOT_MAX;
4235 static const float X_PRECISION;
4236 static const float Y_PRECISION;
Santos Cordonfa5cf462017-04-05 10:37:00 -07004237 static const float X_PRECISION_VIRTUAL;
4238 static const float Y_PRECISION_VIRTUAL;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004239
4240 static const float GEOMETRIC_SCALE;
Jason Gerecke489fda82012-09-07 17:19:40 -07004241 static const TouchAffineTransformation AFFINE_TRANSFORM;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004242
4243 static const VirtualKeyDefinition VIRTUAL_KEYS[2];
4244
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07004245 const std::string UNIQUE_ID = "local:0";
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004246 const std::string SECONDARY_UNIQUE_ID = "local:1";
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07004247
Michael Wrightd02c5b62014-02-10 15:10:22 -08004248 enum Axes {
4249 POSITION = 1 << 0,
4250 TOUCH = 1 << 1,
4251 TOOL = 1 << 2,
4252 PRESSURE = 1 << 3,
4253 ORIENTATION = 1 << 4,
4254 MINOR = 1 << 5,
4255 ID = 1 << 6,
4256 DISTANCE = 1 << 7,
4257 TILT = 1 << 8,
4258 SLOT = 1 << 9,
4259 TOOL_TYPE = 1 << 10,
4260 };
4261
Michael Wrighta9cf4192022-12-01 23:46:39 +00004262 void prepareDisplay(ui::Rotation orientation, std::optional<uint8_t> port = NO_PORT);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004263 void prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port = NO_PORT);
Michael Wrighta9cf4192022-12-01 23:46:39 +00004264 void prepareVirtualDisplay(ui::Rotation orientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004265 void prepareVirtualKeys();
Jason Gerecke489fda82012-09-07 17:19:40 -07004266 void prepareLocationCalibration();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004267 int32_t toRawX(float displayX);
4268 int32_t toRawY(float displayY);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07004269 int32_t toRotatedRawX(float displayX);
4270 int32_t toRotatedRawY(float displayY);
Jason Gerecke489fda82012-09-07 17:19:40 -07004271 float toCookedX(float rawX, float rawY);
4272 float toCookedY(float rawX, float rawY);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004273 float toDisplayX(int32_t rawX);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004274 float toDisplayX(int32_t rawX, int32_t displayWidth);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004275 float toDisplayY(int32_t rawY);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004276 float toDisplayY(int32_t rawY, int32_t displayHeight);
4277
Michael Wrightd02c5b62014-02-10 15:10:22 -08004278};
4279
4280const int32_t TouchInputMapperTest::RAW_X_MIN = 25;
4281const int32_t TouchInputMapperTest::RAW_X_MAX = 1019;
4282const int32_t TouchInputMapperTest::RAW_Y_MIN = 30;
4283const int32_t TouchInputMapperTest::RAW_Y_MAX = 1009;
4284const int32_t TouchInputMapperTest::RAW_TOUCH_MIN = 0;
4285const int32_t TouchInputMapperTest::RAW_TOUCH_MAX = 31;
4286const int32_t TouchInputMapperTest::RAW_TOOL_MIN = 0;
4287const int32_t TouchInputMapperTest::RAW_TOOL_MAX = 15;
Michael Wrightaa449c92017-12-13 21:21:43 +00004288const int32_t TouchInputMapperTest::RAW_PRESSURE_MIN = 0;
4289const int32_t TouchInputMapperTest::RAW_PRESSURE_MAX = 255;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004290const int32_t TouchInputMapperTest::RAW_ORIENTATION_MIN = -7;
4291const int32_t TouchInputMapperTest::RAW_ORIENTATION_MAX = 7;
4292const int32_t TouchInputMapperTest::RAW_DISTANCE_MIN = 0;
4293const int32_t TouchInputMapperTest::RAW_DISTANCE_MAX = 7;
4294const int32_t TouchInputMapperTest::RAW_TILT_MIN = 0;
4295const int32_t TouchInputMapperTest::RAW_TILT_MAX = 150;
4296const int32_t TouchInputMapperTest::RAW_ID_MIN = 0;
4297const int32_t TouchInputMapperTest::RAW_ID_MAX = 9;
4298const int32_t TouchInputMapperTest::RAW_SLOT_MIN = 0;
4299const int32_t TouchInputMapperTest::RAW_SLOT_MAX = 9;
4300const float TouchInputMapperTest::X_PRECISION = float(RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH;
4301const float TouchInputMapperTest::Y_PRECISION = float(RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT;
Santos Cordonfa5cf462017-04-05 10:37:00 -07004302const float TouchInputMapperTest::X_PRECISION_VIRTUAL =
4303 float(RAW_X_MAX - RAW_X_MIN + 1) / VIRTUAL_DISPLAY_WIDTH;
4304const float TouchInputMapperTest::Y_PRECISION_VIRTUAL =
4305 float(RAW_Y_MAX - RAW_Y_MIN + 1) / VIRTUAL_DISPLAY_HEIGHT;
Jason Gerecke489fda82012-09-07 17:19:40 -07004306const TouchAffineTransformation TouchInputMapperTest::AFFINE_TRANSFORM =
4307 TouchAffineTransformation(1, -2, 3, -4, 5, -6);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004308
4309const float TouchInputMapperTest::GEOMETRIC_SCALE =
4310 avg(float(DISPLAY_WIDTH) / (RAW_X_MAX - RAW_X_MIN + 1),
4311 float(DISPLAY_HEIGHT) / (RAW_Y_MAX - RAW_Y_MIN + 1));
4312
4313const VirtualKeyDefinition TouchInputMapperTest::VIRTUAL_KEYS[2] = {
4314 { KEY_HOME, 60, DISPLAY_HEIGHT + 15, 20, 20 },
4315 { KEY_MENU, DISPLAY_HEIGHT - 60, DISPLAY_WIDTH + 15, 20, 20 },
4316};
4317
Michael Wrighta9cf4192022-12-01 23:46:39 +00004318void TouchInputMapperTest::prepareDisplay(ui::Rotation orientation, std::optional<uint8_t> port) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01004319 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
4320 port, ViewportType::INTERNAL);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004321}
4322
4323void TouchInputMapperTest::prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port) {
4324 setDisplayInfoAndReconfigure(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00004325 ui::ROTATION_0, SECONDARY_UNIQUE_ID, port, type);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004326}
4327
Michael Wrighta9cf4192022-12-01 23:46:39 +00004328void TouchInputMapperTest::prepareVirtualDisplay(ui::Rotation orientation) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01004329 setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH, VIRTUAL_DISPLAY_HEIGHT,
4330 orientation, VIRTUAL_DISPLAY_UNIQUE_ID, NO_PORT,
4331 ViewportType::VIRTUAL);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004332}
4333
Michael Wrightd02c5b62014-02-10 15:10:22 -08004334void TouchInputMapperTest::prepareVirtualKeys() {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004335 mFakeEventHub->addVirtualKeyDefinition(EVENTHUB_ID, VIRTUAL_KEYS[0]);
4336 mFakeEventHub->addVirtualKeyDefinition(EVENTHUB_ID, VIRTUAL_KEYS[1]);
4337 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4338 mFakeEventHub->addKey(EVENTHUB_ID, KEY_MENU, 0, AKEYCODE_MENU, POLICY_FLAG_WAKE);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004339}
4340
Jason Gerecke489fda82012-09-07 17:19:40 -07004341void TouchInputMapperTest::prepareLocationCalibration() {
4342 mFakePolicy->setTouchAffineTransformation(AFFINE_TRANSFORM);
4343}
4344
Michael Wrightd02c5b62014-02-10 15:10:22 -08004345int32_t TouchInputMapperTest::toRawX(float displayX) {
4346 return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH + RAW_X_MIN);
4347}
4348
4349int32_t TouchInputMapperTest::toRawY(float displayY) {
4350 return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT + RAW_Y_MIN);
4351}
4352
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07004353int32_t TouchInputMapperTest::toRotatedRawX(float displayX) {
4354 return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_HEIGHT + RAW_X_MIN);
4355}
4356
4357int32_t TouchInputMapperTest::toRotatedRawY(float displayY) {
4358 return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_WIDTH + RAW_Y_MIN);
4359}
4360
Jason Gerecke489fda82012-09-07 17:19:40 -07004361float TouchInputMapperTest::toCookedX(float rawX, float rawY) {
4362 AFFINE_TRANSFORM.applyTo(rawX, rawY);
4363 return rawX;
4364}
4365
4366float TouchInputMapperTest::toCookedY(float rawX, float rawY) {
4367 AFFINE_TRANSFORM.applyTo(rawX, rawY);
4368 return rawY;
4369}
4370
Michael Wrightd02c5b62014-02-10 15:10:22 -08004371float TouchInputMapperTest::toDisplayX(int32_t rawX) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004372 return toDisplayX(rawX, DISPLAY_WIDTH);
4373}
4374
4375float TouchInputMapperTest::toDisplayX(int32_t rawX, int32_t displayWidth) {
4376 return float(rawX - RAW_X_MIN) * displayWidth / (RAW_X_MAX - RAW_X_MIN + 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004377}
4378
4379float TouchInputMapperTest::toDisplayY(int32_t rawY) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004380 return toDisplayY(rawY, DISPLAY_HEIGHT);
4381}
4382
4383float TouchInputMapperTest::toDisplayY(int32_t rawY, int32_t displayHeight) {
4384 return float(rawY - RAW_Y_MIN) * displayHeight / (RAW_Y_MAX - RAW_Y_MIN + 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004385}
4386
4387
4388// --- SingleTouchInputMapperTest ---
4389
4390class SingleTouchInputMapperTest : public TouchInputMapperTest {
4391protected:
4392 void prepareButtons();
4393 void prepareAxes(int axes);
4394
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004395 std::list<NotifyArgs> processDown(SingleTouchInputMapper& mapper, int32_t x, int32_t y);
4396 std::list<NotifyArgs> processMove(SingleTouchInputMapper& mapper, int32_t x, int32_t y);
4397 std::list<NotifyArgs> processUp(SingleTouchInputMapper& mappery);
4398 std::list<NotifyArgs> processPressure(SingleTouchInputMapper& mapper, int32_t pressure);
4399 std::list<NotifyArgs> processToolMajor(SingleTouchInputMapper& mapper, int32_t toolMajor);
4400 std::list<NotifyArgs> processDistance(SingleTouchInputMapper& mapper, int32_t distance);
4401 std::list<NotifyArgs> processTilt(SingleTouchInputMapper& mapper, int32_t tiltX, int32_t tiltY);
4402 std::list<NotifyArgs> processKey(SingleTouchInputMapper& mapper, int32_t code, int32_t value);
4403 std::list<NotifyArgs> processSync(SingleTouchInputMapper& mapper);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004404};
4405
4406void SingleTouchInputMapperTest::prepareButtons() {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004407 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004408}
4409
4410void SingleTouchInputMapperTest::prepareAxes(int axes) {
4411 if (axes & POSITION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004412 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
4413 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004414 }
4415 if (axes & PRESSURE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004416 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_PRESSURE, RAW_PRESSURE_MIN,
4417 RAW_PRESSURE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004418 }
4419 if (axes & TOOL) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004420 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TOOL_WIDTH, RAW_TOOL_MIN, RAW_TOOL_MAX, 0,
4421 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004422 }
4423 if (axes & DISTANCE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004424 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_DISTANCE, RAW_DISTANCE_MIN,
4425 RAW_DISTANCE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004426 }
4427 if (axes & TILT) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004428 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TILT_X, RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
4429 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TILT_Y, RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004430 }
4431}
4432
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004433std::list<NotifyArgs> SingleTouchInputMapperTest::processDown(SingleTouchInputMapper& mapper,
4434 int32_t x, int32_t y) {
4435 std::list<NotifyArgs> args;
4436 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
4437 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, x);
4438 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, y);
4439 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004440}
4441
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004442std::list<NotifyArgs> SingleTouchInputMapperTest::processMove(SingleTouchInputMapper& mapper,
4443 int32_t x, int32_t y) {
4444 std::list<NotifyArgs> args;
4445 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, x);
4446 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, y);
4447 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004448}
4449
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004450std::list<NotifyArgs> SingleTouchInputMapperTest::processUp(SingleTouchInputMapper& mapper) {
4451 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004452}
4453
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004454std::list<NotifyArgs> SingleTouchInputMapperTest::processPressure(SingleTouchInputMapper& mapper,
4455 int32_t pressure) {
4456 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_PRESSURE, pressure);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004457}
4458
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004459std::list<NotifyArgs> SingleTouchInputMapperTest::processToolMajor(SingleTouchInputMapper& mapper,
4460 int32_t toolMajor) {
4461 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TOOL_WIDTH, toolMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004462}
4463
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004464std::list<NotifyArgs> SingleTouchInputMapperTest::processDistance(SingleTouchInputMapper& mapper,
4465 int32_t distance) {
4466 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_DISTANCE, distance);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004467}
4468
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004469std::list<NotifyArgs> SingleTouchInputMapperTest::processTilt(SingleTouchInputMapper& mapper,
4470 int32_t tiltX, int32_t tiltY) {
4471 std::list<NotifyArgs> args;
4472 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TILT_X, tiltX);
4473 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TILT_Y, tiltY);
4474 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004475}
4476
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004477std::list<NotifyArgs> SingleTouchInputMapperTest::processKey(SingleTouchInputMapper& mapper,
4478 int32_t code, int32_t value) {
4479 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004480}
4481
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004482std::list<NotifyArgs> SingleTouchInputMapperTest::processSync(SingleTouchInputMapper& mapper) {
4483 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004484}
4485
Michael Wrightd02c5b62014-02-10 15:10:22 -08004486TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndNotACursor_ReturnsPointer) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004487 prepareButtons();
4488 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00004489 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004490
Josep del Río2d8c79a2023-01-23 19:33:50 +00004491 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004492}
4493
Michael Wrightd02c5b62014-02-10 15:10:22 -08004494TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004495 prepareButtons();
4496 prepareAxes(POSITION);
4497 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00004498 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004499
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004500 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004501}
4502
4503TEST_F(SingleTouchInputMapperTest, GetKeyCodeState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004504 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004505 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004506 prepareButtons();
4507 prepareAxes(POSITION);
4508 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004509 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004510
4511 // Unknown key.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004512 ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004513
4514 // Virtual key is down.
4515 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4516 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4517 processDown(mapper, x, y);
4518 processSync(mapper);
4519 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4520
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004521 ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004522
4523 // Virtual key is up.
4524 processUp(mapper);
4525 processSync(mapper);
4526 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4527
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004528 ASSERT_EQ(AKEY_STATE_UP, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004529}
4530
4531TEST_F(SingleTouchInputMapperTest, GetScanCodeState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004532 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004533 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004534 prepareButtons();
4535 prepareAxes(POSITION);
4536 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004537 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004538
4539 // Unknown key.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004540 ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004541
4542 // Virtual key is down.
4543 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4544 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4545 processDown(mapper, x, y);
4546 processSync(mapper);
4547 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4548
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004549 ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004550
4551 // Virtual key is up.
4552 processUp(mapper);
4553 processSync(mapper);
4554 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4555
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004556 ASSERT_EQ(AKEY_STATE_UP, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004557}
4558
4559TEST_F(SingleTouchInputMapperTest, MarkSupportedKeyCodes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004560 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004561 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004562 prepareButtons();
4563 prepareAxes(POSITION);
4564 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004565 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004566
Michael Wrightd02c5b62014-02-10 15:10:22 -08004567 uint8_t flags[2] = { 0, 0 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07004568 ASSERT_TRUE(
4569 mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_HOME, AKEYCODE_A}, flags));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004570 ASSERT_TRUE(flags[0]);
4571 ASSERT_FALSE(flags[1]);
4572}
4573
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004574TEST_F(SingleTouchInputMapperTest, DeviceTypeChange_RecalculatesRawToDisplayTransform) {
4575 prepareDisplay(ui::ROTATION_0);
4576 prepareAxes(POSITION);
4577 addConfigurationProperty("touch.deviceType", "touchScreen");
4578 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
4579
4580 const int32_t x = 900;
4581 const int32_t y = 75;
4582 std::list<NotifyArgs> args;
4583 args += processDown(mapper, x, y);
4584 args += processSync(mapper);
4585
4586 // Assert that motion event is received in display coordinate space for deviceType touchScreen.
4587 ASSERT_THAT(args,
4588 ElementsAre(VariantWith<NotifyMotionArgs>(
4589 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4590 WithCoords(toDisplayX(x), toDisplayY(y))))));
4591
4592 // Add device type association after the device was created.
4593 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
4594 // Send update to the mapper.
4595 std::list<NotifyArgs> unused =
4596 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
4597 InputReaderConfiguration::Change::DEVICE_TYPE /*changes*/);
4598
4599 args.clear();
4600 args += processDown(mapper, x, y);
4601 args += processSync(mapper);
4602
4603 // Assert that motion event is received in raw coordinate space for deviceType touchNavigation.
4604 ASSERT_THAT(args,
4605 ElementsAre(VariantWith<NotifyMotionArgs>(
4606 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4607 WithCoords(x - RAW_X_MIN, y - RAW_Y_MIN)))));
4608}
4609
Michael Wrightd02c5b62014-02-10 15:10:22 -08004610TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNormally_SendsKeyDownAndKeyUp) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004611 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004612 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004613 prepareButtons();
4614 prepareAxes(POSITION);
4615 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004616 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004617
arthurhungdcef2dc2020-08-11 14:47:50 +08004618 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004619
4620 NotifyKeyArgs args;
4621
4622 // Press virtual key.
4623 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4624 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4625 processDown(mapper, x, y);
4626 processSync(mapper);
4627
4628 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4629 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4630 ASSERT_EQ(DEVICE_ID, args.deviceId);
4631 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4632 ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
4633 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
4634 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
4635 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4636 ASSERT_EQ(KEY_HOME, args.scanCode);
4637 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
4638 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
4639
4640 // Release virtual key.
4641 processUp(mapper);
4642 processSync(mapper);
4643
4644 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4645 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4646 ASSERT_EQ(DEVICE_ID, args.deviceId);
4647 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4648 ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
4649 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
4650 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
4651 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4652 ASSERT_EQ(KEY_HOME, args.scanCode);
4653 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
4654 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
4655
4656 // Should not have sent any motions.
4657 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4658}
4659
4660TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfBounds_SendsKeyDownAndKeyCancel) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004661 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004662 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004663 prepareButtons();
4664 prepareAxes(POSITION);
4665 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004666 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004667
arthurhungdcef2dc2020-08-11 14:47:50 +08004668 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004669
4670 NotifyKeyArgs keyArgs;
4671
4672 // Press virtual key.
4673 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4674 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4675 processDown(mapper, x, y);
4676 processSync(mapper);
4677
4678 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
4679 ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
4680 ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
4681 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
4682 ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
4683 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
4684 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, keyArgs.flags);
4685 ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
4686 ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
4687 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
4688 ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
4689
4690 // Move out of bounds. This should generate a cancel and a pointer down since we moved
4691 // into the display area.
4692 y -= 100;
4693 processMove(mapper, x, y);
4694 processSync(mapper);
4695
4696 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
4697 ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
4698 ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
4699 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
4700 ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
4701 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
4702 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
4703 | AKEY_EVENT_FLAG_CANCELED, keyArgs.flags);
4704 ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
4705 ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
4706 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
4707 ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
4708
4709 NotifyMotionArgs motionArgs;
4710 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4711 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4712 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4713 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4714 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4715 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4716 ASSERT_EQ(0, motionArgs.flags);
4717 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4718 ASSERT_EQ(0, motionArgs.buttonState);
4719 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004720 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004721 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004722 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004723 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4724 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4725 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4726 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4727 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4728
4729 // Keep moving out of bounds. Should generate a pointer move.
4730 y -= 50;
4731 processMove(mapper, x, y);
4732 processSync(mapper);
4733
4734 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4735 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4736 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4737 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4738 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4739 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
4740 ASSERT_EQ(0, motionArgs.flags);
4741 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4742 ASSERT_EQ(0, motionArgs.buttonState);
4743 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004744 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004745 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004746 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004747 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4748 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4749 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4750 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4751 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4752
4753 // Release out of bounds. Should generate a pointer up.
4754 processUp(mapper);
4755 processSync(mapper);
4756
4757 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4758 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4759 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4760 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4761 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4762 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4763 ASSERT_EQ(0, motionArgs.flags);
4764 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4765 ASSERT_EQ(0, motionArgs.buttonState);
4766 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004767 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004768 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004769 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004770 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4771 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4772 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4773 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4774 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4775
4776 // Should not have sent any more keys or motions.
4777 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4778 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4779}
4780
4781TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMovesIn_SendsDownAsTouchEntersDisplay) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004782 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004783 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004784 prepareButtons();
4785 prepareAxes(POSITION);
4786 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004787 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004788
arthurhungdcef2dc2020-08-11 14:47:50 +08004789 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004790
4791 NotifyMotionArgs motionArgs;
4792
4793 // Initially go down out of bounds.
4794 int32_t x = -10;
4795 int32_t y = -10;
4796 processDown(mapper, x, y);
4797 processSync(mapper);
4798
4799 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4800
4801 // Move into the display area. Should generate a pointer down.
4802 x = 50;
4803 y = 75;
4804 processMove(mapper, x, y);
4805 processSync(mapper);
4806
4807 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4808 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4809 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4810 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4811 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4812 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4813 ASSERT_EQ(0, motionArgs.flags);
4814 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4815 ASSERT_EQ(0, motionArgs.buttonState);
4816 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004817 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004818 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004819 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004820 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4821 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4822 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4823 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4824 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4825
4826 // Release. Should generate a pointer up.
4827 processUp(mapper);
4828 processSync(mapper);
4829
4830 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4831 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4832 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4833 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4834 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4835 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4836 ASSERT_EQ(0, motionArgs.flags);
4837 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4838 ASSERT_EQ(0, motionArgs.buttonState);
4839 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004840 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004841 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004842 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004843 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4844 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4845 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4846 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4847 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4848
4849 // Should not have sent any more keys or motions.
4850 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4851 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4852}
4853
Santos Cordonfa5cf462017-04-05 10:37:00 -07004854TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture_VirtualDisplay) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004855 addConfigurationProperty("touch.deviceType", "touchScreen");
4856 addConfigurationProperty("touch.displayId", VIRTUAL_DISPLAY_UNIQUE_ID);
4857
Michael Wrighta9cf4192022-12-01 23:46:39 +00004858 prepareVirtualDisplay(ui::ROTATION_0);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004859 prepareButtons();
4860 prepareAxes(POSITION);
4861 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004862 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Santos Cordonfa5cf462017-04-05 10:37:00 -07004863
arthurhungdcef2dc2020-08-11 14:47:50 +08004864 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004865
4866 NotifyMotionArgs motionArgs;
4867
4868 // Down.
4869 int32_t x = 100;
4870 int32_t y = 125;
4871 processDown(mapper, x, y);
4872 processSync(mapper);
4873
4874 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4875 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4876 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4877 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4878 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4879 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4880 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4881 ASSERT_EQ(0, motionArgs.flags);
4882 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4883 ASSERT_EQ(0, motionArgs.buttonState);
4884 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004885 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004886 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004887 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004888 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4889 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4890 1, 0, 0, 0, 0, 0, 0, 0));
4891 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4892 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4893 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4894
4895 // Move.
4896 x += 50;
4897 y += 75;
4898 processMove(mapper, x, y);
4899 processSync(mapper);
4900
4901 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4902 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4903 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4904 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4905 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4906 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4907 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
4908 ASSERT_EQ(0, motionArgs.flags);
4909 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4910 ASSERT_EQ(0, motionArgs.buttonState);
4911 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004912 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004913 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004914 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004915 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4916 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4917 1, 0, 0, 0, 0, 0, 0, 0));
4918 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4919 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4920 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4921
4922 // Up.
4923 processUp(mapper);
4924 processSync(mapper);
4925
4926 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4927 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4928 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4929 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4930 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4931 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4932 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4933 ASSERT_EQ(0, motionArgs.flags);
4934 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4935 ASSERT_EQ(0, motionArgs.buttonState);
4936 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004937 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004938 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004939 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004940 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4941 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4942 1, 0, 0, 0, 0, 0, 0, 0));
4943 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4944 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4945 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4946
4947 // Should not have sent any more keys or motions.
4948 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4949 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4950}
4951
Michael Wrightd02c5b62014-02-10 15:10:22 -08004952TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004953 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004954 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004955 prepareButtons();
4956 prepareAxes(POSITION);
4957 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004958 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004959
arthurhungdcef2dc2020-08-11 14:47:50 +08004960 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004961
4962 NotifyMotionArgs motionArgs;
4963
4964 // Down.
4965 int32_t x = 100;
4966 int32_t y = 125;
4967 processDown(mapper, x, y);
4968 processSync(mapper);
4969
4970 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4971 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4972 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4973 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4974 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4975 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4976 ASSERT_EQ(0, motionArgs.flags);
4977 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4978 ASSERT_EQ(0, motionArgs.buttonState);
4979 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004980 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004981 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004982 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004983 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4984 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4985 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4986 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4987 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4988
4989 // Move.
4990 x += 50;
4991 y += 75;
4992 processMove(mapper, x, y);
4993 processSync(mapper);
4994
4995 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4996 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4997 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4998 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4999 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5000 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5001 ASSERT_EQ(0, motionArgs.flags);
5002 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5003 ASSERT_EQ(0, motionArgs.buttonState);
5004 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005005 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08005006 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005007 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005008 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5009 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
5010 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5011 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5012 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5013
5014 // Up.
5015 processUp(mapper);
5016 processSync(mapper);
5017
5018 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5019 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5020 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5021 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5022 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5023 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5024 ASSERT_EQ(0, motionArgs.flags);
5025 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5026 ASSERT_EQ(0, motionArgs.buttonState);
5027 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005028 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08005029 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005030 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005031 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5032 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
5033 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5034 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5035 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5036
5037 // Should not have sent any more keys or motions.
5038 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5039 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5040}
5041
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005042TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_DoesNotRotateMotions) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005043 addConfigurationProperty("touch.deviceType", "touchScreen");
5044 prepareButtons();
5045 prepareAxes(POSITION);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005046 // InputReader works in the un-rotated coordinate space, so orientation-aware devices do not
5047 // need to be rotated. Touchscreens are orientation-aware by default.
Arpit Singha8c236b2023-04-25 13:56:05 +00005048 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005049
5050 NotifyMotionArgs args;
5051
5052 // Rotation 90.
Michael Wrighta9cf4192022-12-01 23:46:39 +00005053 prepareDisplay(ui::ROTATION_90);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005054 processDown(mapper, toRawX(50), toRawY(75));
5055 processSync(mapper);
5056
5057 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5058 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5059 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5060
5061 processUp(mapper);
5062 processSync(mapper);
5063 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5064}
5065
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005066TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_RotatesMotions) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005067 addConfigurationProperty("touch.deviceType", "touchScreen");
5068 prepareButtons();
5069 prepareAxes(POSITION);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005070 // Since InputReader works in the un-rotated coordinate space, only devices that are not
5071 // orientation-aware are affected by display rotation.
5072 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00005073 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005074
5075 NotifyMotionArgs args;
5076
5077 // Rotation 0.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005078 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005079 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005080 processDown(mapper, toRawX(50), toRawY(75));
5081 processSync(mapper);
5082
5083 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5084 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5085 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5086
5087 processUp(mapper);
5088 processSync(mapper);
5089 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5090
5091 // Rotation 90.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005092 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005093 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005094 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005095 processSync(mapper);
5096
5097 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5098 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5099 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5100
5101 processUp(mapper);
5102 processSync(mapper);
5103 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5104
5105 // Rotation 180.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005106 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005107 prepareDisplay(ui::ROTATION_180);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005108 processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
5109 processSync(mapper);
5110
5111 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5112 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5113 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5114
5115 processUp(mapper);
5116 processSync(mapper);
5117 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5118
5119 // Rotation 270.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005120 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005121 prepareDisplay(ui::ROTATION_270);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005122 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005123 processSync(mapper);
5124
5125 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5126 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5127 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5128
5129 processUp(mapper);
5130 processSync(mapper);
5131 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5132}
5133
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005134TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation0_RotatesMotions) {
5135 addConfigurationProperty("touch.deviceType", "touchScreen");
5136 prepareButtons();
5137 prepareAxes(POSITION);
5138 addConfigurationProperty("touch.orientationAware", "1");
5139 addConfigurationProperty("touch.orientation", "ORIENTATION_0");
5140 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005141 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005142 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005143 NotifyMotionArgs args;
5144
5145 // Orientation 0.
5146 processDown(mapper, toRawX(50), toRawY(75));
5147 processSync(mapper);
5148
5149 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5150 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5151 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5152
5153 processUp(mapper);
5154 processSync(mapper);
5155 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5156}
5157
5158TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation90_RotatesMotions) {
5159 addConfigurationProperty("touch.deviceType", "touchScreen");
5160 prepareButtons();
5161 prepareAxes(POSITION);
5162 addConfigurationProperty("touch.orientationAware", "1");
5163 addConfigurationProperty("touch.orientation", "ORIENTATION_90");
5164 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005165 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005166 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005167 NotifyMotionArgs args;
5168
5169 // Orientation 90.
5170 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
5171 processSync(mapper);
5172
5173 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5174 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5175 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5176
5177 processUp(mapper);
5178 processSync(mapper);
5179 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5180}
5181
5182TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation180_RotatesMotions) {
5183 addConfigurationProperty("touch.deviceType", "touchScreen");
5184 prepareButtons();
5185 prepareAxes(POSITION);
5186 addConfigurationProperty("touch.orientationAware", "1");
5187 addConfigurationProperty("touch.orientation", "ORIENTATION_180");
5188 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005189 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005190 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005191 NotifyMotionArgs args;
5192
5193 // Orientation 180.
5194 processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
5195 processSync(mapper);
5196
5197 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5198 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5199 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5200
5201 processUp(mapper);
5202 processSync(mapper);
5203 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5204}
5205
5206TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation270_RotatesMotions) {
5207 addConfigurationProperty("touch.deviceType", "touchScreen");
5208 prepareButtons();
5209 prepareAxes(POSITION);
5210 addConfigurationProperty("touch.orientationAware", "1");
5211 addConfigurationProperty("touch.orientation", "ORIENTATION_270");
5212 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005213 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005214 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005215 NotifyMotionArgs args;
5216
5217 // Orientation 270.
5218 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
5219 processSync(mapper);
5220
5221 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5222 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5223 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5224
5225 processUp(mapper);
5226 processSync(mapper);
5227 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5228}
5229
5230TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationSpecified_RotatesMotionWithDisplay) {
5231 addConfigurationProperty("touch.deviceType", "touchScreen");
5232 prepareButtons();
5233 prepareAxes(POSITION);
5234 // Since InputReader works in the un-rotated coordinate space, only devices that are not
5235 // orientation-aware are affected by display rotation.
5236 addConfigurationProperty("touch.orientationAware", "0");
5237 addConfigurationProperty("touch.orientation", "ORIENTATION_90");
Arpit Singha8c236b2023-04-25 13:56:05 +00005238 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005239
5240 NotifyMotionArgs args;
5241
5242 // Orientation 90, Rotation 0.
5243 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005244 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005245 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
5246 processSync(mapper);
5247
5248 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5249 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5250 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5251
5252 processUp(mapper);
5253 processSync(mapper);
5254 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5255
5256 // Orientation 90, Rotation 90.
5257 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005258 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005259 processDown(mapper, toRawX(50), toRawY(75));
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005260 processSync(mapper);
5261
5262 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5263 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5264 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5265
5266 processUp(mapper);
5267 processSync(mapper);
5268 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5269
5270 // Orientation 90, Rotation 180.
5271 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005272 prepareDisplay(ui::ROTATION_180);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005273 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
5274 processSync(mapper);
5275
5276 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5277 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5278 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5279
5280 processUp(mapper);
5281 processSync(mapper);
5282 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5283
5284 // Orientation 90, Rotation 270.
5285 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005286 prepareDisplay(ui::ROTATION_270);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005287 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 -07005288 processSync(mapper);
5289
5290 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5291 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5292 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5293
5294 processUp(mapper);
5295 processSync(mapper);
5296 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5297}
5298
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005299TEST_F(SingleTouchInputMapperTest, Process_IgnoresTouchesOutsidePhysicalFrame) {
5300 addConfigurationProperty("touch.deviceType", "touchScreen");
5301 prepareButtons();
5302 prepareAxes(POSITION);
5303 addConfigurationProperty("touch.orientationAware", "1");
5304 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005305 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005306
5307 // Set a physical frame in the display viewport.
5308 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
5309 viewport->physicalLeft = 20;
5310 viewport->physicalTop = 600;
5311 viewport->physicalRight = 30;
5312 viewport->physicalBottom = 610;
5313 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00005314 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005315
5316 // Start the touch.
5317 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
5318 processSync(mapper);
5319
5320 // Expect all input starting outside the physical frame to be ignored.
5321 const std::array<Point, 6> outsidePoints = {
5322 {{0, 0}, {19, 605}, {31, 605}, {25, 599}, {25, 611}, {DISPLAY_WIDTH, DISPLAY_HEIGHT}}};
5323 for (const auto& p : outsidePoints) {
5324 processMove(mapper, toRawX(p.x), toRawY(p.y));
5325 processSync(mapper);
5326 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5327 }
5328
5329 // Move the touch into the physical frame.
5330 processMove(mapper, toRawX(25), toRawY(605));
5331 processSync(mapper);
5332 NotifyMotionArgs args;
5333 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5334 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
5335 EXPECT_NEAR(25, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5336 EXPECT_NEAR(605, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5337
5338 // Once the touch down is reported, continue reporting input, even if it is outside the frame.
5339 for (const auto& p : outsidePoints) {
5340 processMove(mapper, toRawX(p.x), toRawY(p.y));
5341 processSync(mapper);
5342 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5343 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
5344 EXPECT_NEAR(p.x, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5345 EXPECT_NEAR(p.y, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5346 }
5347
5348 processUp(mapper);
5349 processSync(mapper);
5350 EXPECT_NO_FATAL_FAILURE(
5351 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
5352}
5353
Harry Cutts1db43992023-06-19 17:05:07 +00005354TEST_F(SingleTouchInputMapperTest, Process_DoesntCheckPhysicalFrameForTouchpads) {
Harry Cutts1db43992023-06-19 17:05:07 +00005355 addConfigurationProperty("touch.deviceType", "pointer");
5356 prepareAxes(POSITION);
5357 prepareDisplay(ui::ROTATION_0);
5358 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
5359
5360 // Set a physical frame in the display viewport.
5361 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
5362 viewport->physicalLeft = 20;
5363 viewport->physicalTop = 600;
5364 viewport->physicalRight = 30;
5365 viewport->physicalBottom = 610;
5366 mFakePolicy->updateViewport(*viewport);
5367 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
5368
5369 // Start the touch.
5370 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
5371 processSync(mapper);
5372
5373 // Expect all input starting outside the physical frame to result in NotifyMotionArgs being
5374 // produced.
5375 const std::array<Point, 6> outsidePoints = {
5376 {{0, 0}, {19, 605}, {31, 605}, {25, 599}, {25, 611}, {DISPLAY_WIDTH, DISPLAY_HEIGHT}}};
5377 for (const auto& p : outsidePoints) {
5378 processMove(mapper, toRawX(p.x), toRawY(p.y));
5379 processSync(mapper);
5380 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5381 }
5382}
5383
Michael Wrightd02c5b62014-02-10 15:10:22 -08005384TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005385 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005386 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005387 prepareButtons();
5388 prepareAxes(POSITION | PRESSURE | TOOL | DISTANCE | TILT);
Arpit Singha8c236b2023-04-25 13:56:05 +00005389 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005390
5391 // These calculations are based on the input device calibration documentation.
5392 int32_t rawX = 100;
5393 int32_t rawY = 200;
5394 int32_t rawPressure = 10;
5395 int32_t rawToolMajor = 12;
5396 int32_t rawDistance = 2;
5397 int32_t rawTiltX = 30;
5398 int32_t rawTiltY = 110;
5399
5400 float x = toDisplayX(rawX);
5401 float y = toDisplayY(rawY);
5402 float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
5403 float size = float(rawToolMajor) / RAW_TOOL_MAX;
5404 float tool = float(rawToolMajor) * GEOMETRIC_SCALE;
5405 float distance = float(rawDistance);
5406
5407 float tiltCenter = (RAW_TILT_MAX + RAW_TILT_MIN) * 0.5f;
5408 float tiltScale = M_PI / 180;
5409 float tiltXAngle = (rawTiltX - tiltCenter) * tiltScale;
5410 float tiltYAngle = (rawTiltY - tiltCenter) * tiltScale;
5411 float orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
5412 float tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
5413
5414 processDown(mapper, rawX, rawY);
5415 processPressure(mapper, rawPressure);
5416 processToolMajor(mapper, rawToolMajor);
5417 processDistance(mapper, rawDistance);
5418 processTilt(mapper, rawTiltX, rawTiltY);
5419 processSync(mapper);
5420
5421 NotifyMotionArgs args;
5422 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5423 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
5424 x, y, pressure, size, tool, tool, tool, tool, orientation, distance));
5425 ASSERT_EQ(tilt, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TILT));
Prabir Pradhan9a53b552024-06-04 02:59:40 +00005426 ASSERT_EQ(args.flags,
5427 AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION |
5428 AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005429}
5430
Jason Gerecke489fda82012-09-07 17:19:40 -07005431TEST_F(SingleTouchInputMapperTest, Process_XYAxes_AffineCalibration) {
Jason Gerecke489fda82012-09-07 17:19:40 -07005432 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005433 prepareDisplay(ui::ROTATION_0);
Jason Gerecke489fda82012-09-07 17:19:40 -07005434 prepareLocationCalibration();
5435 prepareButtons();
5436 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005437 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Jason Gerecke489fda82012-09-07 17:19:40 -07005438
5439 int32_t rawX = 100;
5440 int32_t rawY = 200;
5441
5442 float x = toDisplayX(toCookedX(rawX, rawY));
5443 float y = toDisplayY(toCookedY(rawX, rawY));
5444
5445 processDown(mapper, rawX, rawY);
5446 processSync(mapper);
5447
5448 NotifyMotionArgs args;
5449 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5450 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
5451 x, y, 1, 0, 0, 0, 0, 0, 0, 0));
5452}
5453
Michael Wrightd02c5b62014-02-10 15:10:22 -08005454TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllButtons) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005455 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005456 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005457 prepareButtons();
5458 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005459 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005460
5461 NotifyMotionArgs motionArgs;
5462 NotifyKeyArgs keyArgs;
5463
5464 processDown(mapper, 100, 200);
5465 processSync(mapper);
5466 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5467 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5468 ASSERT_EQ(0, motionArgs.buttonState);
5469
5470 // press BTN_LEFT, release BTN_LEFT
5471 processKey(mapper, BTN_LEFT, 1);
5472 processSync(mapper);
5473 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5474 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5475 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
5476
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005477 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5478 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5479 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
5480
Michael Wrightd02c5b62014-02-10 15:10:22 -08005481 processKey(mapper, BTN_LEFT, 0);
5482 processSync(mapper);
5483 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005484 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005485 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005486
5487 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005488 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005489 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005490
5491 // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
5492 processKey(mapper, BTN_RIGHT, 1);
5493 processKey(mapper, BTN_MIDDLE, 1);
5494 processSync(mapper);
5495 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5496 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5497 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
5498 motionArgs.buttonState);
5499
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005500 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5501 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5502 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
5503
5504 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5505 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5506 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
5507 motionArgs.buttonState);
5508
Michael Wrightd02c5b62014-02-10 15:10:22 -08005509 processKey(mapper, BTN_RIGHT, 0);
5510 processSync(mapper);
5511 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005512 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005513 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005514
5515 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005516 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005517 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005518
5519 processKey(mapper, BTN_MIDDLE, 0);
5520 processSync(mapper);
5521 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005522 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005523 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005524
5525 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005526 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005527 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005528
5529 // press BTN_BACK, release BTN_BACK
5530 processKey(mapper, BTN_BACK, 1);
5531 processSync(mapper);
5532 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5533 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5534 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005535
Michael Wrightd02c5b62014-02-10 15:10:22 -08005536 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005537 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005538 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
5539
5540 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5541 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5542 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005543
5544 processKey(mapper, BTN_BACK, 0);
5545 processSync(mapper);
5546 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005547 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005548 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005549
5550 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005551 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005552 ASSERT_EQ(0, motionArgs.buttonState);
5553
Michael Wrightd02c5b62014-02-10 15:10:22 -08005554 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5555 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5556 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
5557
5558 // press BTN_SIDE, release BTN_SIDE
5559 processKey(mapper, BTN_SIDE, 1);
5560 processSync(mapper);
5561 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5562 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5563 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005564
Michael Wrightd02c5b62014-02-10 15:10:22 -08005565 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(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
5568
5569 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5570 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5571 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005572
5573 processKey(mapper, BTN_SIDE, 0);
5574 processSync(mapper);
5575 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005576 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005577 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005578
5579 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005580 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005581 ASSERT_EQ(0, motionArgs.buttonState);
5582
Michael Wrightd02c5b62014-02-10 15:10:22 -08005583 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5584 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5585 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
5586
5587 // press BTN_FORWARD, release BTN_FORWARD
5588 processKey(mapper, BTN_FORWARD, 1);
5589 processSync(mapper);
5590 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5591 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5592 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005593
Michael Wrightd02c5b62014-02-10 15:10:22 -08005594 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005595 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005596 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
5597
5598 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5599 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5600 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005601
5602 processKey(mapper, BTN_FORWARD, 0);
5603 processSync(mapper);
5604 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005605 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005606 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005607
5608 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005609 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005610 ASSERT_EQ(0, motionArgs.buttonState);
5611
Michael Wrightd02c5b62014-02-10 15:10:22 -08005612 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5613 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5614 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
5615
5616 // press BTN_EXTRA, release BTN_EXTRA
5617 processKey(mapper, BTN_EXTRA, 1);
5618 processSync(mapper);
5619 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5620 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5621 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005622
Michael Wrightd02c5b62014-02-10 15:10:22 -08005623 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005624 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005625 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
5626
5627 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5628 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5629 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005630
5631 processKey(mapper, BTN_EXTRA, 0);
5632 processSync(mapper);
5633 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005634 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005635 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005636
5637 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005638 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005639 ASSERT_EQ(0, motionArgs.buttonState);
5640
Michael Wrightd02c5b62014-02-10 15:10:22 -08005641 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5642 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5643 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
5644
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005645 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5646
Michael Wrightd02c5b62014-02-10 15:10:22 -08005647 // press BTN_STYLUS, release BTN_STYLUS
5648 processKey(mapper, BTN_STYLUS, 1);
5649 processSync(mapper);
5650 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5651 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005652 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
5653
5654 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5655 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5656 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005657
5658 processKey(mapper, BTN_STYLUS, 0);
5659 processSync(mapper);
5660 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005661 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005662 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005663
5664 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005665 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005666 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005667
5668 // press BTN_STYLUS2, release BTN_STYLUS2
5669 processKey(mapper, BTN_STYLUS2, 1);
5670 processSync(mapper);
5671 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5672 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005673 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
5674
5675 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5676 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5677 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005678
5679 processKey(mapper, BTN_STYLUS2, 0);
5680 processSync(mapper);
5681 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005682 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005683 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005684
5685 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005686 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005687 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005688
5689 // release touch
5690 processUp(mapper);
5691 processSync(mapper);
5692 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5693 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5694 ASSERT_EQ(0, motionArgs.buttonState);
5695}
5696
5697TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005698 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005699 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005700 prepareButtons();
5701 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005702 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005703
5704 NotifyMotionArgs motionArgs;
5705
5706 // default tool type is finger
5707 processDown(mapper, 100, 200);
5708 processSync(mapper);
5709 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5710 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005711 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005712
5713 // eraser
5714 processKey(mapper, BTN_TOOL_RUBBER, 1);
5715 processSync(mapper);
5716 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5717 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005718 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005719
5720 // stylus
5721 processKey(mapper, BTN_TOOL_RUBBER, 0);
5722 processKey(mapper, BTN_TOOL_PEN, 1);
5723 processSync(mapper);
5724 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5725 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005726 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005727
5728 // brush
5729 processKey(mapper, BTN_TOOL_PEN, 0);
5730 processKey(mapper, BTN_TOOL_BRUSH, 1);
5731 processSync(mapper);
5732 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5733 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005734 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005735
5736 // pencil
5737 processKey(mapper, BTN_TOOL_BRUSH, 0);
5738 processKey(mapper, BTN_TOOL_PENCIL, 1);
5739 processSync(mapper);
5740 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5741 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005742 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005743
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08005744 // air-brush
Michael Wrightd02c5b62014-02-10 15:10:22 -08005745 processKey(mapper, BTN_TOOL_PENCIL, 0);
5746 processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
5747 processSync(mapper);
5748 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5749 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005750 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005751
5752 // mouse
5753 processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
5754 processKey(mapper, BTN_TOOL_MOUSE, 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::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005759
5760 // lens
5761 processKey(mapper, BTN_TOOL_MOUSE, 0);
5762 processKey(mapper, BTN_TOOL_LENS, 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::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005767
5768 // double-tap
5769 processKey(mapper, BTN_TOOL_LENS, 0);
5770 processKey(mapper, BTN_TOOL_DOUBLETAP, 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::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005775
5776 // triple-tap
5777 processKey(mapper, BTN_TOOL_DOUBLETAP, 0);
5778 processKey(mapper, BTN_TOOL_TRIPLETAP, 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::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005783
5784 // quad-tap
5785 processKey(mapper, BTN_TOOL_TRIPLETAP, 0);
5786 processKey(mapper, BTN_TOOL_QUADTAP, 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::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005791
5792 // finger
5793 processKey(mapper, BTN_TOOL_QUADTAP, 0);
5794 processKey(mapper, BTN_TOOL_FINGER, 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::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005799
5800 // stylus trumps finger
5801 processKey(mapper, BTN_TOOL_PEN, 1);
5802 processSync(mapper);
5803 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5804 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005805 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005806
5807 // eraser trumps stylus
5808 processKey(mapper, BTN_TOOL_RUBBER, 1);
5809 processSync(mapper);
5810 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5811 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005812 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005813
5814 // mouse trumps eraser
5815 processKey(mapper, BTN_TOOL_MOUSE, 1);
5816 processSync(mapper);
5817 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5818 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005819 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005820
5821 // back to default tool type
5822 processKey(mapper, BTN_TOOL_MOUSE, 0);
5823 processKey(mapper, BTN_TOOL_RUBBER, 0);
5824 processKey(mapper, BTN_TOOL_PEN, 0);
5825 processKey(mapper, BTN_TOOL_FINGER, 0);
5826 processSync(mapper);
5827 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5828 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005829 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005830}
5831
5832TEST_F(SingleTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005833 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005834 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005835 prepareButtons();
5836 prepareAxes(POSITION);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08005837 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_FINGER, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005838 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005839
5840 NotifyMotionArgs motionArgs;
5841
5842 // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0
5843 processKey(mapper, BTN_TOOL_FINGER, 1);
5844 processMove(mapper, 100, 200);
5845 processSync(mapper);
5846 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5847 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5848 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5849 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5850
5851 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5852 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5853 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5854 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5855
5856 // move a little
5857 processMove(mapper, 150, 250);
5858 processSync(mapper);
5859 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5860 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5861 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5862 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5863
5864 // down when BTN_TOUCH is pressed, pressure defaults to 1
5865 processKey(mapper, BTN_TOUCH, 1);
5866 processSync(mapper);
5867 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5868 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5869 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5870 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5871
5872 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5873 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5874 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5875 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5876
5877 // up when BTN_TOUCH is released, hover restored
5878 processKey(mapper, BTN_TOUCH, 0);
5879 processSync(mapper);
5880 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5881 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5882 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5883 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5884
5885 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5886 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5887 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5888 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5889
5890 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5891 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5892 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5893 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5894
5895 // exit hover when pointer goes away
5896 processKey(mapper, BTN_TOOL_FINGER, 0);
5897 processSync(mapper);
5898 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5899 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5900 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5901 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5902}
5903
5904TEST_F(SingleTouchInputMapperTest, Process_WhenAbsPressureIsPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005905 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005906 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005907 prepareButtons();
5908 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00005909 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005910
5911 NotifyMotionArgs motionArgs;
5912
5913 // initially hovering because pressure is 0
5914 processDown(mapper, 100, 200);
5915 processPressure(mapper, 0);
5916 processSync(mapper);
5917 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5918 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5919 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5920 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5921
5922 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5923 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5924 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5925 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5926
5927 // move a little
5928 processMove(mapper, 150, 250);
5929 processSync(mapper);
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 // down when pressure is non-zero
5936 processPressure(mapper, RAW_PRESSURE_MAX);
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 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5944 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5945 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5946 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5947
5948 // up when pressure becomes 0, hover restored
5949 processPressure(mapper, 0);
5950 processSync(mapper);
5951 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5952 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5953 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5954 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5955
5956 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5957 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5958 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5959 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5960
5961 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5962 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5963 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5964 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5965
5966 // exit hover when pointer goes away
5967 processUp(mapper);
5968 processSync(mapper);
5969 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5970 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5971 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5972 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5973}
5974
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00005975TEST_F(SingleTouchInputMapperTest, Reset_CancelsOngoingGesture) {
5976 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005977 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00005978 prepareButtons();
5979 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00005980 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00005981
5982 // Touch down.
5983 processDown(mapper, 100, 200);
5984 processPressure(mapper, 1);
5985 processSync(mapper);
5986 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
5987 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
5988
5989 // Reset the mapper. This should cancel the ongoing gesture.
5990 resetMapper(mapper, ARBITRARY_TIME);
5991 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
5992 WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
5993
5994 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5995}
5996
Prabir Pradhanafabcde2022-09-27 19:32:43 +00005997TEST_F(SingleTouchInputMapperTest, Reset_RecreatesTouchState) {
5998 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005999 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006000 prepareButtons();
6001 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00006002 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006003
6004 // Set the initial state for the touch pointer.
6005 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_X, 100);
6006 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_Y, 200);
6007 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_PRESSURE, RAW_PRESSURE_MAX);
6008 mFakeEventHub->setScanCodeState(EVENTHUB_ID, BTN_TOUCH, 1);
6009
6010 // Reset the mapper. When the mapper is reset, we expect it to attempt to recreate the touch
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006011 // state by reading the current axis values. Since there was no ongoing gesture, calling reset
6012 // does not generate any events.
6013 resetMapper(mapper, ARBITRARY_TIME);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006014
6015 // Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
6016 // the recreated touch state to generate a down event.
6017 processSync(mapper);
6018 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6019 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPressure(1.f))));
6020
6021 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6022}
6023
lilinnan687e58f2022-07-19 16:00:50 +08006024TEST_F(SingleTouchInputMapperTest,
6025 Process_WhenViewportDisplayIdChanged_TouchIsCanceledAndDeviceIsReset) {
6026 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006027 prepareDisplay(ui::ROTATION_0);
lilinnan687e58f2022-07-19 16:00:50 +08006028 prepareButtons();
6029 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006030 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
lilinnan687e58f2022-07-19 16:00:50 +08006031 NotifyMotionArgs motionArgs;
6032
6033 // Down.
Prabir Pradhan3e5ec702022-07-29 16:26:24 +00006034 processDown(mapper, 100, 200);
lilinnan687e58f2022-07-19 16:00:50 +08006035 processSync(mapper);
6036
6037 // We should receive a down event
6038 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6039 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6040
6041 // Change display id
6042 clearViewports();
6043 prepareSecondaryDisplay(ViewportType::INTERNAL);
6044
6045 // We should receive a cancel event
6046 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6047 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
6048 // Then receive reset called
6049 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6050}
6051
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006052TEST_F(SingleTouchInputMapperTest,
6053 Process_WhenViewportActiveStatusChanged_TouchIsCanceledAndDeviceIsReset) {
6054 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006055 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006056 prepareButtons();
6057 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006058 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006059 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6060 NotifyMotionArgs motionArgs;
6061
6062 // Start a new gesture.
6063 processDown(mapper, 100, 200);
6064 processSync(mapper);
6065 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6066 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6067
6068 // Make the viewport inactive. This will put the device in disabled mode.
6069 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6070 viewport->isActive = false;
6071 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006072 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006073
6074 // We should receive a cancel event for the ongoing gesture.
6075 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6076 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
6077 // Then we should be notified that the device was reset.
6078 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6079
6080 // No events are generated while the viewport is inactive.
6081 processMove(mapper, 101, 201);
6082 processSync(mapper);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006083 processUp(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006084 processSync(mapper);
6085 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6086
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006087 // Start a new gesture while the viewport is still inactive.
6088 processDown(mapper, 300, 400);
6089 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_X, 300);
6090 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_Y, 400);
6091 mFakeEventHub->setScanCodeState(EVENTHUB_ID, BTN_TOUCH, 1);
6092 processSync(mapper);
6093
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006094 // Make the viewport active again. The device should resume processing events.
6095 viewport->isActive = true;
6096 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006097 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006098
6099 // The device is reset because it changes back to direct mode, without generating any events.
6100 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6101 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6102
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006103 // In the next sync, the touch state that was recreated when the device was reset is reported.
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006104 processSync(mapper);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006105 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6106 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006107
6108 // No more events.
6109 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6110 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
6111}
6112
Prabir Pradhan211ba622022-10-31 21:09:21 +00006113TEST_F(SingleTouchInputMapperTest, ButtonIsReleasedOnTouchUp) {
6114 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006115 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan211ba622022-10-31 21:09:21 +00006116 prepareButtons();
6117 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006118 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan211ba622022-10-31 21:09:21 +00006119 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6120
6121 // Press a stylus button.
6122 processKey(mapper, BTN_STYLUS, 1);
6123 processSync(mapper);
6124
6125 // Start a touch gesture and ensure the BUTTON_PRESS event is generated.
6126 processDown(mapper, 100, 200);
6127 processSync(mapper);
6128 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6129 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6130 WithCoords(toDisplayX(100), toDisplayY(200)),
6131 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6132 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6133 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
6134 WithCoords(toDisplayX(100), toDisplayY(200)),
6135 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6136
6137 // Release the touch gesture. Ensure that the BUTTON_RELEASE event is generated even though
6138 // the button has not actually been released, since there will be no pointers through which the
6139 // button state can be reported. The event is generated at the location of the pointer before
6140 // it went up.
6141 processUp(mapper);
6142 processSync(mapper);
6143 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6144 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
6145 WithCoords(toDisplayX(100), toDisplayY(200)), WithButtonState(0))));
6146 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6147 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6148 WithCoords(toDisplayX(100), toDisplayY(200)), WithButtonState(0))));
6149}
6150
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00006151TEST_F(SingleTouchInputMapperTest, StylusButtonMotionEventsDisabled) {
6152 addConfigurationProperty("touch.deviceType", "touchScreen");
6153 prepareDisplay(ui::ROTATION_0);
6154 prepareButtons();
6155 prepareAxes(POSITION);
6156
6157 mFakePolicy->setStylusButtonMotionEventsEnabled(false);
6158
Arpit Singha8c236b2023-04-25 13:56:05 +00006159 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00006160 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6161
6162 // Press a stylus button.
6163 processKey(mapper, BTN_STYLUS, 1);
6164 processSync(mapper);
6165
6166 // Start a touch gesture and ensure that the stylus button is not reported.
6167 processDown(mapper, 100, 200);
6168 processSync(mapper);
6169 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6170 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithButtonState(0))));
6171
6172 // Release and press the stylus button again.
6173 processKey(mapper, BTN_STYLUS, 0);
6174 processSync(mapper);
6175 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6176 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
6177 processKey(mapper, BTN_STYLUS, 1);
6178 processSync(mapper);
6179 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6180 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
6181
6182 // Release the touch gesture.
6183 processUp(mapper);
6184 processSync(mapper);
6185 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6186 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
6187
6188 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6189}
6190
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006191TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsSetToTouchNavigation_setsCorrectType) {
6192 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
6193 prepareDisplay(ui::ROTATION_0);
6194 prepareButtons();
6195 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006196 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006197 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6198
Prabir Pradhan9cf8f322024-06-18 20:22:42 +00006199 ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION | AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006200}
6201
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006202TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsChangedToTouchNavigation_updatesDeviceType) {
6203 // Initialize the device without setting device source to touch navigation.
6204 addConfigurationProperty("touch.deviceType", "touchScreen");
6205 prepareDisplay(ui::ROTATION_0);
6206 prepareButtons();
6207 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006208 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006209
6210 // Ensure that the device is created as a touchscreen, not touch navigation.
6211 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
6212
6213 // Add device type association after the device was created.
6214 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
6215
6216 // Send update to the mapper.
6217 std::list<NotifyArgs> unused2 =
6218 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006219 InputReaderConfiguration::Change::DEVICE_TYPE /*changes*/);
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006220
6221 // Check whether device type update was successful.
Prabir Pradhan9cf8f322024-06-18 20:22:42 +00006222 ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION | AINPUT_SOURCE_TOUCHPAD, mDevice->getSources());
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006223}
6224
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006225TEST_F(SingleTouchInputMapperTest, HoverEventsOutsidePhysicalFrameAreIgnored) {
6226 // Initialize the device without setting device source to touch navigation.
6227 addConfigurationProperty("touch.deviceType", "touchScreen");
6228 prepareDisplay(ui::ROTATION_0);
6229 prepareButtons();
6230 prepareAxes(POSITION);
6231 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
6232
6233 // Set a physical frame in the display viewport.
6234 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6235 viewport->physicalLeft = 0;
6236 viewport->physicalTop = 0;
6237 viewport->physicalRight = DISPLAY_WIDTH / 2;
6238 viewport->physicalBottom = DISPLAY_HEIGHT / 2;
6239 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006240 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006241
Arpit Singha8c236b2023-04-25 13:56:05 +00006242 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006243
6244 // Hovering inside the physical frame produces events.
6245 processKey(mapper, BTN_TOOL_PEN, 1);
6246 processMove(mapper, RAW_X_MIN + 1, RAW_Y_MIN + 1);
6247 processSync(mapper);
6248 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6249 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)));
6250 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6251 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)));
6252
6253 // Leaving the physical frame ends the hovering gesture.
6254 processMove(mapper, RAW_X_MAX - 1, RAW_Y_MAX - 1);
6255 processSync(mapper);
6256 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6257 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT)));
6258
6259 // Moving outside the physical frame does not produce events.
6260 processMove(mapper, RAW_X_MAX - 2, RAW_Y_MAX - 2);
6261 processSync(mapper);
6262 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6263
6264 // Re-entering the physical frame produces events.
6265 processMove(mapper, RAW_X_MIN, RAW_Y_MIN);
6266 processSync(mapper);
6267 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6268 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)));
6269 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6270 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)));
6271}
6272
Prabir Pradhan5632d622021-09-06 07:57:20 -07006273// --- TouchDisplayProjectionTest ---
6274
6275class TouchDisplayProjectionTest : public SingleTouchInputMapperTest {
6276public:
6277 // The values inside DisplayViewport are expected to be pre-rotated. This updates the current
6278 // DisplayViewport to pre-rotate the values. The viewport's physical display will be set to the
6279 // rotated equivalent of the given un-rotated physical display bounds.
Prabir Pradhana9df3162022-12-05 23:57:27 +00006280 void configurePhysicalDisplay(ui::Rotation orientation, Rect naturalPhysicalDisplay,
6281 int32_t naturalDisplayWidth = DISPLAY_WIDTH,
6282 int32_t naturalDisplayHeight = DISPLAY_HEIGHT) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006283 uint32_t inverseRotationFlags;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006284 auto rotatedWidth = naturalDisplayWidth;
6285 auto rotatedHeight = naturalDisplayHeight;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006286 switch (orientation) {
Michael Wrighta9cf4192022-12-01 23:46:39 +00006287 case ui::ROTATION_90:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006288 inverseRotationFlags = ui::Transform::ROT_270;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006289 std::swap(rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006290 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006291 case ui::ROTATION_180:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006292 inverseRotationFlags = ui::Transform::ROT_180;
6293 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006294 case ui::ROTATION_270:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006295 inverseRotationFlags = ui::Transform::ROT_90;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006296 std::swap(rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006297 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006298 case ui::ROTATION_0:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006299 inverseRotationFlags = ui::Transform::ROT_0;
6300 break;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006301 }
6302
Prabir Pradhana9df3162022-12-05 23:57:27 +00006303 const ui::Transform rotation(inverseRotationFlags, rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006304 const Rect rotatedPhysicalDisplay = rotation.transform(naturalPhysicalDisplay);
6305
6306 std::optional<DisplayViewport> internalViewport =
6307 *mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6308 DisplayViewport& v = *internalViewport;
6309 v.displayId = DISPLAY_ID;
6310 v.orientation = orientation;
6311
6312 v.logicalLeft = 0;
6313 v.logicalTop = 0;
6314 v.logicalRight = 100;
6315 v.logicalBottom = 100;
6316
6317 v.physicalLeft = rotatedPhysicalDisplay.left;
6318 v.physicalTop = rotatedPhysicalDisplay.top;
6319 v.physicalRight = rotatedPhysicalDisplay.right;
6320 v.physicalBottom = rotatedPhysicalDisplay.bottom;
6321
Prabir Pradhana9df3162022-12-05 23:57:27 +00006322 v.deviceWidth = rotatedWidth;
6323 v.deviceHeight = rotatedHeight;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006324
6325 v.isActive = true;
6326 v.uniqueId = UNIQUE_ID;
6327 v.type = ViewportType::INTERNAL;
6328 mFakePolicy->updateViewport(v);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006329 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006330 }
6331
6332 void assertReceivedMove(const Point& point) {
6333 NotifyMotionArgs motionArgs;
6334 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6335 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006336 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Prabir Pradhan5632d622021-09-06 07:57:20 -07006337 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], point.x, point.y,
6338 1, 0, 0, 0, 0, 0, 0, 0));
6339 }
6340};
6341
6342TEST_F(TouchDisplayProjectionTest, IgnoresTouchesOutsidePhysicalDisplay) {
6343 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006344 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006345
6346 prepareButtons();
6347 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006348 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan5632d622021-09-06 07:57:20 -07006349
6350 NotifyMotionArgs motionArgs;
6351
6352 // Configure the DisplayViewport such that the logical display maps to a subsection of
6353 // the display panel called the physical display. Here, the physical display is bounded by the
6354 // points (10, 20) and (70, 160) inside the display space, which is of the size 400 x 800.
6355 static const Rect kPhysicalDisplay{10, 20, 70, 160};
6356 static const std::array<Point, 6> kPointsOutsidePhysicalDisplay{
6357 {{-10, -10}, {0, 0}, {5, 100}, {50, 15}, {75, 100}, {50, 165}}};
6358
Michael Wrighta9cf4192022-12-01 23:46:39 +00006359 for (auto orientation : {ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180, ui::ROTATION_270}) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006360 configurePhysicalDisplay(orientation, kPhysicalDisplay);
6361
6362 // Touches outside the physical display should be ignored, and should not generate any
6363 // events. Ensure touches at the following points that lie outside of the physical display
6364 // area do not generate any events.
6365 for (const auto& point : kPointsOutsidePhysicalDisplay) {
6366 processDown(mapper, toRawX(point.x), toRawY(point.y));
6367 processSync(mapper);
6368 processUp(mapper);
6369 processSync(mapper);
6370 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled())
6371 << "Unexpected event generated for touch outside physical display at point: "
6372 << point.x << ", " << point.y;
6373 }
6374 }
6375}
6376
6377TEST_F(TouchDisplayProjectionTest, EmitsTouchDownAfterEnteringPhysicalDisplay) {
6378 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006379 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006380
6381 prepareButtons();
6382 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006383 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan5632d622021-09-06 07:57:20 -07006384
6385 NotifyMotionArgs motionArgs;
6386
6387 // Configure the DisplayViewport such that the logical display maps to a subsection of
6388 // the display panel called the physical display. Here, the physical display is bounded by the
6389 // points (10, 20) and (70, 160) inside the display space, which is of the size 400 x 800.
6390 static const Rect kPhysicalDisplay{10, 20, 70, 160};
6391
Michael Wrighta9cf4192022-12-01 23:46:39 +00006392 for (auto orientation : {ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180, ui::ROTATION_270}) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006393 configurePhysicalDisplay(orientation, kPhysicalDisplay);
6394
6395 // Touches that start outside the physical display should be ignored until it enters the
6396 // physical display bounds, at which point it should generate a down event. Start a touch at
6397 // the point (5, 100), which is outside the physical display bounds.
6398 static const Point kOutsidePoint{5, 100};
6399 processDown(mapper, toRawX(kOutsidePoint.x), toRawY(kOutsidePoint.y));
6400 processSync(mapper);
6401 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6402
6403 // Move the touch into the physical display area. This should generate a pointer down.
6404 processMove(mapper, toRawX(11), toRawY(21));
6405 processSync(mapper);
6406 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6407 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006408 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Prabir Pradhan5632d622021-09-06 07:57:20 -07006409 ASSERT_NO_FATAL_FAILURE(
6410 assertPointerCoords(motionArgs.pointerCoords[0], 11, 21, 1, 0, 0, 0, 0, 0, 0, 0));
6411
6412 // Move the touch inside the physical display area. This should generate a pointer move.
6413 processMove(mapper, toRawX(69), toRawY(159));
6414 processSync(mapper);
6415 assertReceivedMove({69, 159});
6416
6417 // Move outside the physical display area. Since the pointer is already down, this should
6418 // now continue generating events.
6419 processMove(mapper, toRawX(kOutsidePoint.x), toRawY(kOutsidePoint.y));
6420 processSync(mapper);
6421 assertReceivedMove(kOutsidePoint);
6422
6423 // Release. This should generate a pointer up.
6424 processUp(mapper);
6425 processSync(mapper);
6426 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6427 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
6428 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], kOutsidePoint.x,
6429 kOutsidePoint.y, 1, 0, 0, 0, 0, 0, 0, 0));
6430
6431 // Ensure no more events were generated.
6432 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
6433 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6434 }
6435}
6436
Prabir Pradhana9df3162022-12-05 23:57:27 +00006437// --- TouchscreenPrecisionTests ---
6438
6439// This test suite is used to ensure that touchscreen devices are scaled and configured correctly
6440// in various orientations and with different display rotations. We configure the touchscreen to
6441// have a higher resolution than that of the display by an integer scale factor in each axis so that
6442// we can enforce that coordinates match precisely as expected.
6443class TouchscreenPrecisionTestsFixture : public TouchDisplayProjectionTest,
6444 public ::testing::WithParamInterface<ui::Rotation> {
6445public:
6446 void SetUp() override {
6447 SingleTouchInputMapperTest::SetUp();
6448
6449 // Prepare the raw axes to have twice the resolution of the display in the X axis and
6450 // four times the resolution of the display in the Y axis.
6451 prepareButtons();
6452 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, PRECISION_RAW_X_MIN, PRECISION_RAW_X_MAX,
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006453 PRECISION_RAW_X_FLAT, PRECISION_RAW_X_FUZZ,
6454 PRECISION_RAW_X_RES);
Prabir Pradhana9df3162022-12-05 23:57:27 +00006455 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, PRECISION_RAW_Y_MIN, PRECISION_RAW_Y_MAX,
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006456 PRECISION_RAW_Y_FLAT, PRECISION_RAW_Y_FUZZ,
6457 PRECISION_RAW_Y_RES);
Prabir Pradhana9df3162022-12-05 23:57:27 +00006458 }
6459
6460 static const int32_t PRECISION_RAW_X_MIN = TouchInputMapperTest::RAW_X_MIN;
6461 static const int32_t PRECISION_RAW_X_MAX = PRECISION_RAW_X_MIN + DISPLAY_WIDTH * 2 - 1;
6462 static const int32_t PRECISION_RAW_Y_MIN = TouchInputMapperTest::RAW_Y_MIN;
6463 static const int32_t PRECISION_RAW_Y_MAX = PRECISION_RAW_Y_MIN + DISPLAY_HEIGHT * 4 - 1;
6464
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006465 static const int32_t PRECISION_RAW_X_RES = 50; // units per millimeter
6466 static const int32_t PRECISION_RAW_Y_RES = 100; // units per millimeter
6467
6468 static const int32_t PRECISION_RAW_X_FLAT = 16;
6469 static const int32_t PRECISION_RAW_Y_FLAT = 32;
6470
6471 static const int32_t PRECISION_RAW_X_FUZZ = 4;
6472 static const int32_t PRECISION_RAW_Y_FUZZ = 8;
6473
Prabir Pradhana9df3162022-12-05 23:57:27 +00006474 static const std::array<Point, 4> kRawCorners;
6475};
6476
6477const std::array<Point, 4> TouchscreenPrecisionTestsFixture::kRawCorners = {{
6478 {PRECISION_RAW_X_MIN, PRECISION_RAW_Y_MIN}, // left-top
6479 {PRECISION_RAW_X_MAX, PRECISION_RAW_Y_MIN}, // right-top
6480 {PRECISION_RAW_X_MAX, PRECISION_RAW_Y_MAX}, // right-bottom
6481 {PRECISION_RAW_X_MIN, PRECISION_RAW_Y_MAX}, // left-bottom
6482}};
6483
6484// Tests for how the touchscreen is oriented relative to the natural orientation of the display.
6485// For example, if a touchscreen is configured with an orientation of 90 degrees, it is a portrait
6486// touchscreen panel that is used on a device whose natural display orientation is in landscape.
6487TEST_P(TouchscreenPrecisionTestsFixture, OrientationPrecision) {
6488 enum class Orientation {
6489 ORIENTATION_0 = ui::toRotationInt(ui::ROTATION_0),
6490 ORIENTATION_90 = ui::toRotationInt(ui::ROTATION_90),
6491 ORIENTATION_180 = ui::toRotationInt(ui::ROTATION_180),
6492 ORIENTATION_270 = ui::toRotationInt(ui::ROTATION_270),
6493 ftl_last = ORIENTATION_270,
6494 };
6495 using Orientation::ORIENTATION_0, Orientation::ORIENTATION_90, Orientation::ORIENTATION_180,
6496 Orientation::ORIENTATION_270;
6497 static const std::map<Orientation, std::array<vec2, 4> /*mappedCorners*/> kMappedCorners = {
6498 {ORIENTATION_0, {{{0, 0}, {479.5, 0}, {479.5, 799.75}, {0, 799.75}}}},
6499 {ORIENTATION_90, {{{0, 479.5}, {0, 0}, {799.75, 0}, {799.75, 479.5}}}},
6500 {ORIENTATION_180, {{{479.5, 799.75}, {0, 799.75}, {0, 0}, {479.5, 0}}}},
6501 {ORIENTATION_270, {{{799.75, 0}, {799.75, 479.5}, {0, 479.5}, {0, 0}}}},
6502 };
6503
6504 const auto touchscreenOrientation = static_cast<Orientation>(ui::toRotationInt(GetParam()));
6505
6506 // Configure the touchscreen as being installed in the one of the four different orientations
6507 // relative to the display.
6508 addConfigurationProperty("touch.deviceType", "touchScreen");
6509 addConfigurationProperty("touch.orientation", ftl::enum_string(touchscreenOrientation).c_str());
6510 prepareDisplay(ui::ROTATION_0);
6511
Arpit Singha8c236b2023-04-25 13:56:05 +00006512 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhana9df3162022-12-05 23:57:27 +00006513
6514 // If the touchscreen is installed in a rotated orientation relative to the display (i.e. in
6515 // orientations of either 90 or 270) this means the display's natural resolution will be
6516 // flipped.
6517 const bool displayRotated =
6518 touchscreenOrientation == ORIENTATION_90 || touchscreenOrientation == ORIENTATION_270;
6519 const int32_t width = displayRotated ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
6520 const int32_t height = displayRotated ? DISPLAY_WIDTH : DISPLAY_HEIGHT;
6521 const Rect physicalFrame{0, 0, width, height};
6522 configurePhysicalDisplay(ui::ROTATION_0, physicalFrame, width, height);
6523
6524 const auto& expectedPoints = kMappedCorners.at(touchscreenOrientation);
6525 const float expectedPrecisionX = displayRotated ? 4 : 2;
6526 const float expectedPrecisionY = displayRotated ? 2 : 4;
6527
6528 // Test all four corners.
6529 for (int i = 0; i < 4; i++) {
6530 const auto& raw = kRawCorners[i];
6531 processDown(mapper, raw.x, raw.y);
6532 processSync(mapper);
6533 const auto& expected = expectedPoints[i];
6534 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6535 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6536 WithCoords(expected.x, expected.y),
6537 WithPrecision(expectedPrecisionX, expectedPrecisionY))))
6538 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6539 << "with touchscreen orientation "
6540 << ftl::enum_string(touchscreenOrientation).c_str() << ", expected point ("
6541 << expected.x << ", " << expected.y << ").";
6542 processUp(mapper);
6543 processSync(mapper);
6544 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6545 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6546 WithCoords(expected.x, expected.y))));
6547 }
6548}
6549
Prabir Pradhan82687402022-12-06 01:32:53 +00006550TEST_P(TouchscreenPrecisionTestsFixture, RotationPrecisionWhenOrientationAware) {
6551 static const std::map<ui::Rotation /*rotation*/, std::array<vec2, 4> /*mappedCorners*/>
6552 kMappedCorners = {
6553 {ui::ROTATION_0, {{{0, 0}, {479.5, 0}, {479.5, 799.75}, {0, 799.75}}}},
6554 {ui::ROTATION_90, {{{0.5, 0}, {480, 0}, {480, 799.75}, {0.5, 799.75}}}},
6555 {ui::ROTATION_180, {{{0.5, 0.25}, {480, 0.25}, {480, 800}, {0.5, 800}}}},
6556 {ui::ROTATION_270, {{{0, 0.25}, {479.5, 0.25}, {479.5, 800}, {0, 800}}}},
6557 };
6558
6559 const ui::Rotation displayRotation = GetParam();
6560
6561 addConfigurationProperty("touch.deviceType", "touchScreen");
6562 prepareDisplay(displayRotation);
6563
Arpit Singha8c236b2023-04-25 13:56:05 +00006564 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan82687402022-12-06 01:32:53 +00006565
6566 const auto& expectedPoints = kMappedCorners.at(displayRotation);
6567
6568 // Test all four corners.
6569 for (int i = 0; i < 4; i++) {
6570 const auto& expected = expectedPoints[i];
6571 const auto& raw = kRawCorners[i];
6572 processDown(mapper, raw.x, raw.y);
6573 processSync(mapper);
6574 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6575 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6576 WithCoords(expected.x, expected.y), WithPrecision(2, 4))))
6577 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6578 << "with display rotation " << ui::toCString(displayRotation)
6579 << ", expected point (" << expected.x << ", " << expected.y << ").";
6580 processUp(mapper);
6581 processSync(mapper);
6582 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6583 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6584 WithCoords(expected.x, expected.y))));
6585 }
6586}
6587
Prabir Pradhan3e798762022-12-02 21:02:11 +00006588TEST_P(TouchscreenPrecisionTestsFixture, RotationPrecisionOrientationAwareInOri270) {
6589 static const std::map<ui::Rotation /*orientation*/, std::array<vec2, 4> /*mappedCorners*/>
6590 kMappedCorners = {
6591 {ui::ROTATION_0, {{{799.75, 0}, {799.75, 479.5}, {0, 479.5}, {0, 0}}}},
6592 {ui::ROTATION_90, {{{800, 0}, {800, 479.5}, {0.25, 479.5}, {0.25, 0}}}},
6593 {ui::ROTATION_180, {{{800, 0.5}, {800, 480}, {0.25, 480}, {0.25, 0.5}}}},
6594 {ui::ROTATION_270, {{{799.75, 0.5}, {799.75, 480}, {0, 480}, {0, 0.5}}}},
6595 };
6596
6597 const ui::Rotation displayRotation = GetParam();
6598
6599 addConfigurationProperty("touch.deviceType", "touchScreen");
6600 addConfigurationProperty("touch.orientation", "ORIENTATION_270");
6601
Arpit Singha8c236b2023-04-25 13:56:05 +00006602 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan3e798762022-12-02 21:02:11 +00006603
6604 // Ori 270, so width and height swapped
6605 const Rect physicalFrame{0, 0, DISPLAY_HEIGHT, DISPLAY_WIDTH};
6606 prepareDisplay(displayRotation);
6607 configurePhysicalDisplay(displayRotation, physicalFrame, DISPLAY_HEIGHT, DISPLAY_WIDTH);
6608
6609 const auto& expectedPoints = kMappedCorners.at(displayRotation);
6610
6611 // Test all four corners.
6612 for (int i = 0; i < 4; i++) {
6613 const auto& expected = expectedPoints[i];
6614 const auto& raw = kRawCorners[i];
6615 processDown(mapper, raw.x, raw.y);
6616 processSync(mapper);
6617 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6618 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6619 WithCoords(expected.x, expected.y), WithPrecision(4, 2))))
6620 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6621 << "with display rotation " << ui::toCString(displayRotation)
6622 << ", expected point (" << expected.x << ", " << expected.y << ").";
6623 processUp(mapper);
6624 processSync(mapper);
6625 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6626 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6627 WithCoords(expected.x, expected.y))));
6628 }
6629}
6630
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006631TEST_P(TouchscreenPrecisionTestsFixture, MotionRangesAreOrientedInRotatedDisplay) {
6632 const ui::Rotation displayRotation = GetParam();
6633
6634 addConfigurationProperty("touch.deviceType", "touchScreen");
6635 prepareDisplay(displayRotation);
6636
6637 __attribute__((unused)) SingleTouchInputMapper& mapper =
Arpit Singha8c236b2023-04-25 13:56:05 +00006638 constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006639
6640 const InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
6641 // MotionRanges use display pixels as their units
6642 const auto* xRange = deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHSCREEN);
6643 const auto* yRange = deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_Y, AINPUT_SOURCE_TOUCHSCREEN);
6644
6645 // The MotionRanges should be oriented in the rotated display's coordinate space
6646 const bool displayRotated =
6647 displayRotation == ui::ROTATION_90 || displayRotation == ui::ROTATION_270;
6648
6649 constexpr float MAX_X = 479.5;
6650 constexpr float MAX_Y = 799.75;
6651 EXPECT_EQ(xRange->min, 0.f);
6652 EXPECT_EQ(yRange->min, 0.f);
6653 EXPECT_EQ(xRange->max, displayRotated ? MAX_Y : MAX_X);
6654 EXPECT_EQ(yRange->max, displayRotated ? MAX_X : MAX_Y);
6655
6656 EXPECT_EQ(xRange->flat, 8.f);
6657 EXPECT_EQ(yRange->flat, 8.f);
6658
6659 EXPECT_EQ(xRange->fuzz, 2.f);
6660 EXPECT_EQ(yRange->fuzz, 2.f);
6661
6662 EXPECT_EQ(xRange->resolution, 25.f); // pixels per millimeter
6663 EXPECT_EQ(yRange->resolution, 25.f); // pixels per millimeter
6664}
6665
Prabir Pradhana9df3162022-12-05 23:57:27 +00006666// Run the precision tests for all rotations.
6667INSTANTIATE_TEST_SUITE_P(TouchscreenPrecisionTests, TouchscreenPrecisionTestsFixture,
6668 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
6669 ui::ROTATION_270),
6670 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
6671 return ftl::enum_string(testParamInfo.param);
6672 });
6673
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006674// --- ExternalStylusFusionTest ---
6675
6676class ExternalStylusFusionTest : public SingleTouchInputMapperTest {
6677public:
Prabir Pradhan7ff19a12024-07-29 22:40:31 +00006678 void SetUp() override {
6679 SingleTouchInputMapperTest::SetUp();
6680 mExternalStylusDeviceInfo = {};
6681 mStylusState = {};
6682 }
6683
6684 SingleTouchInputMapper& initializeInputMapperWithExternalStylus(bool supportsPressure = true) {
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006685 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006686 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006687 prepareButtons();
6688 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006689 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006690
Prabir Pradhan7ff19a12024-07-29 22:40:31 +00006691 if (supportsPressure) {
6692 mExternalStylusDeviceInfo.addMotionRange(AMOTION_EVENT_AXIS_PRESSURE,
6693 AINPUT_SOURCE_STYLUS, 0.0f, 1.0f, 0.0f, 0.0f,
6694 0.0f);
6695 mStylusState.pressure = 0.f;
6696 }
6697
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006698 mStylusState.when = ARBITRARY_TIME;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006699 mStylusState.toolType = ToolType::STYLUS;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006700 mReader->getContext()->setExternalStylusDevices({mExternalStylusDeviceInfo});
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006701 configureDevice(InputReaderConfiguration::Change::EXTERNAL_STYLUS_PRESENCE);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006702 processExternalStylusState(mapper);
6703 return mapper;
6704 }
6705
6706 std::list<NotifyArgs> processExternalStylusState(InputMapper& mapper) {
6707 std::list<NotifyArgs> generatedArgs = mapper.updateExternalStylusState(mStylusState);
6708 for (const NotifyArgs& args : generatedArgs) {
6709 mFakeListener->notify(args);
6710 }
6711 // Loop the reader to flush the input listener queue.
6712 mReader->loopOnce();
6713 return generatedArgs;
6714 }
6715
6716protected:
6717 StylusState mStylusState{};
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006718
6719 void testStartFusedStylusGesture(SingleTouchInputMapper& mapper) {
6720 auto toolTypeSource =
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006721 AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006722
6723 // The first pointer is withheld.
6724 processDown(mapper, 100, 200);
6725 processSync(mapper);
6726 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6727 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6728 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6729
6730 // The external stylus reports pressure. The withheld finger pointer is released as a
6731 // stylus.
6732 mStylusState.pressure = 1.f;
6733 processExternalStylusState(mapper);
6734 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6735 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6736 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6737
6738 // Subsequent pointer events are not withheld.
6739 processMove(mapper, 101, 201);
6740 processSync(mapper);
6741 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6742 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6743
6744 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6745 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6746 }
6747
6748 void testSuccessfulFusionGesture(SingleTouchInputMapper& mapper) {
6749 ASSERT_NO_FATAL_FAILURE(testStartFusedStylusGesture(mapper));
6750
6751 // Releasing the touch pointer ends the gesture.
6752 processUp(mapper);
6753 processSync(mapper);
6754 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006755 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(STYLUS_FUSION_SOURCE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006756 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006757
6758 mStylusState.pressure = 0.f;
6759 processExternalStylusState(mapper);
6760 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6761 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6762 }
6763
6764 void testUnsuccessfulFusionGesture(SingleTouchInputMapper& mapper) {
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006765 // When stylus fusion is not successful, events should be reported with the original source.
6766 // In this case, it is from a touchscreen.
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006767 auto toolTypeSource =
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006768 AllOf(WithSource(AINPUT_SOURCE_TOUCHSCREEN), WithToolType(ToolType::FINGER));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006769
6770 // The first pointer is withheld when an external stylus is connected,
6771 // and a timeout is requested.
6772 processDown(mapper, 100, 200);
6773 processSync(mapper);
6774 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6775 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6776 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6777
6778 // If the timeout expires early, it is requested again.
6779 handleTimeout(mapper, ARBITRARY_TIME + 1);
6780 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6781 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6782
6783 // When the timeout expires, the withheld touch is released as a finger pointer.
6784 handleTimeout(mapper, ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT);
6785 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6786 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6787
6788 // Subsequent pointer events are not withheld.
6789 processMove(mapper, 101, 201);
6790 processSync(mapper);
6791 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6792 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6793 processUp(mapper);
6794 processSync(mapper);
6795 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6796 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP))));
6797
6798 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6799 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6800 }
6801
6802private:
6803 InputDeviceInfo mExternalStylusDeviceInfo{};
6804};
6805
Prabir Pradhan7ff19a12024-07-29 22:40:31 +00006806TEST_F(ExternalStylusFusionTest, UsesBluetoothStylusSourceWithPressure) {
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006807 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006808 ASSERT_EQ(STYLUS_FUSION_SOURCE, mapper.getSources());
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006809}
6810
Prabir Pradhan7ff19a12024-07-29 22:40:31 +00006811TEST_F(ExternalStylusFusionTest, DoesNotUseBluetoothStylusSourceWithoutPressure) {
6812 SingleTouchInputMapper& mapper =
6813 initializeInputMapperWithExternalStylus(/*supportsPressure=*/false);
6814 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
6815}
6816
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006817TEST_F(ExternalStylusFusionTest, UnsuccessfulFusion) {
6818 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6819 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6820}
6821
6822TEST_F(ExternalStylusFusionTest, SuccessfulFusion_TouchFirst) {
6823 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6824 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6825}
6826
6827// Test a successful stylus fusion gesture where the pressure is reported by the external
6828// before the touch is reported by the touchscreen.
6829TEST_F(ExternalStylusFusionTest, SuccessfulFusion_PressureFirst) {
6830 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006831 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006832
6833 // The external stylus reports pressure first. It is ignored for now.
6834 mStylusState.pressure = 1.f;
6835 processExternalStylusState(mapper);
6836 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6837 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6838
6839 // When the touch goes down afterwards, it is reported as a stylus pointer.
6840 processDown(mapper, 100, 200);
6841 processSync(mapper);
6842 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6843 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6844 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6845
6846 processMove(mapper, 101, 201);
6847 processSync(mapper);
6848 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6849 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6850 processUp(mapper);
6851 processSync(mapper);
6852 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6853 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP))));
6854
6855 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6856 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6857}
6858
6859TEST_F(ExternalStylusFusionTest, FusionIsRepeatedForEachNewGesture) {
6860 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6861
6862 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6863 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6864
6865 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6866 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6867 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6868 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6869}
6870
6871TEST_F(ExternalStylusFusionTest, FusedPointerReportsPressureChanges) {
6872 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006873 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006874
6875 mStylusState.pressure = 0.8f;
6876 processExternalStylusState(mapper);
6877 processDown(mapper, 100, 200);
6878 processSync(mapper);
6879 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6880 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6881 WithPressure(0.8f))));
6882 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6883
6884 // The external stylus reports a pressure change. We wait for some time for a touch event.
6885 mStylusState.pressure = 0.6f;
6886 processExternalStylusState(mapper);
6887 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6888 ASSERT_NO_FATAL_FAILURE(
6889 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6890
6891 // If a touch is reported within the timeout, it reports the updated pressure.
6892 processMove(mapper, 101, 201);
6893 processSync(mapper);
6894 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6895 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6896 WithPressure(0.6f))));
6897 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6898
6899 // There is another pressure change.
6900 mStylusState.pressure = 0.5f;
6901 processExternalStylusState(mapper);
6902 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6903 ASSERT_NO_FATAL_FAILURE(
6904 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6905
6906 // If a touch is not reported within the timeout, a move event is generated to report
6907 // the new pressure.
6908 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
6909 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6910 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6911 WithPressure(0.5f))));
6912
6913 // If a zero pressure is reported before the touch goes up, the previous pressure value is
6914 // repeated indefinitely.
6915 mStylusState.pressure = 0.0f;
6916 processExternalStylusState(mapper);
6917 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6918 ASSERT_NO_FATAL_FAILURE(
6919 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6920 processMove(mapper, 102, 202);
6921 processSync(mapper);
6922 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6923 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6924 WithPressure(0.5f))));
6925 processMove(mapper, 103, 203);
6926 processSync(mapper);
6927 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6928 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6929 WithPressure(0.5f))));
6930
6931 processUp(mapper);
6932 processSync(mapper);
6933 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006934 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(STYLUS_FUSION_SOURCE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006935 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006936
6937 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6938 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6939}
6940
6941TEST_F(ExternalStylusFusionTest, FusedPointerReportsToolTypeChanges) {
6942 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006943 auto source = WithSource(STYLUS_FUSION_SOURCE);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006944
6945 mStylusState.pressure = 1.f;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006946 mStylusState.toolType = ToolType::ERASER;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006947 processExternalStylusState(mapper);
6948 processDown(mapper, 100, 200);
6949 processSync(mapper);
6950 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6951 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006952 WithToolType(ToolType::ERASER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006953 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6954
6955 // The external stylus reports a tool change. We wait for some time for a touch event.
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006956 mStylusState.toolType = ToolType::STYLUS;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006957 processExternalStylusState(mapper);
6958 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6959 ASSERT_NO_FATAL_FAILURE(
6960 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6961
6962 // If a touch is reported within the timeout, it reports the updated pressure.
6963 processMove(mapper, 101, 201);
6964 processSync(mapper);
6965 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6966 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006967 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006968 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6969
6970 // There is another tool type change.
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006971 mStylusState.toolType = ToolType::FINGER;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006972 processExternalStylusState(mapper);
6973 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6974 ASSERT_NO_FATAL_FAILURE(
6975 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6976
6977 // If a touch is not reported within the timeout, a move event is generated to report
6978 // the new tool type.
6979 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
6980 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6981 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006982 WithToolType(ToolType::FINGER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006983
6984 processUp(mapper);
6985 processSync(mapper);
6986 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6987 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006988 WithToolType(ToolType::FINGER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006989
6990 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6991 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6992}
6993
6994TEST_F(ExternalStylusFusionTest, FusedPointerReportsButtons) {
6995 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006996 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006997
6998 ASSERT_NO_FATAL_FAILURE(testStartFusedStylusGesture(mapper));
6999
7000 // The external stylus reports a button change. We wait for some time for a touch event.
7001 mStylusState.buttons = AMOTION_EVENT_BUTTON_STYLUS_PRIMARY;
7002 processExternalStylusState(mapper);
7003 ASSERT_NO_FATAL_FAILURE(
7004 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7005
7006 // If a touch is reported within the timeout, it reports the updated button state.
7007 processMove(mapper, 101, 201);
7008 processSync(mapper);
7009 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7010 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
7011 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
7012 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7013 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
7014 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
7015 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7016
7017 // The button is now released.
7018 mStylusState.buttons = 0;
7019 processExternalStylusState(mapper);
7020 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7021 ASSERT_NO_FATAL_FAILURE(
7022 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7023
7024 // If a touch is not reported within the timeout, a move event is generated to report
7025 // the new button state.
7026 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007027 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7028 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
7029 WithButtonState(0))));
7030 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhan124ea442022-10-28 20:27:44 +00007031 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
7032 WithButtonState(0))));
7033
7034 processUp(mapper);
7035 processSync(mapper);
7036 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007037 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
7038
7039 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7040 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7041}
7042
Michael Wrightd02c5b62014-02-10 15:10:22 -08007043// --- MultiTouchInputMapperTest ---
7044
7045class MultiTouchInputMapperTest : public TouchInputMapperTest {
7046protected:
7047 void prepareAxes(int axes);
7048
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007049 void processPosition(MultiTouchInputMapper& mapper, int32_t x, int32_t y);
7050 void processTouchMajor(MultiTouchInputMapper& mapper, int32_t touchMajor);
7051 void processTouchMinor(MultiTouchInputMapper& mapper, int32_t touchMinor);
7052 void processToolMajor(MultiTouchInputMapper& mapper, int32_t toolMajor);
7053 void processToolMinor(MultiTouchInputMapper& mapper, int32_t toolMinor);
7054 void processOrientation(MultiTouchInputMapper& mapper, int32_t orientation);
7055 void processPressure(MultiTouchInputMapper& mapper, int32_t pressure);
7056 void processDistance(MultiTouchInputMapper& mapper, int32_t distance);
7057 void processId(MultiTouchInputMapper& mapper, int32_t id);
7058 void processSlot(MultiTouchInputMapper& mapper, int32_t slot);
7059 void processToolType(MultiTouchInputMapper& mapper, int32_t toolType);
7060 void processKey(MultiTouchInputMapper& mapper, int32_t code, int32_t value);
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00007061 void processHidUsage(MultiTouchInputMapper& mapper, int32_t usageCode, int32_t value);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007062 void processMTSync(MultiTouchInputMapper& mapper);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00007063 void processSync(MultiTouchInputMapper& mapper, nsecs_t eventTime = ARBITRARY_TIME,
7064 nsecs_t readTime = READ_TIME);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007065};
7066
7067void MultiTouchInputMapperTest::prepareAxes(int axes) {
7068 if (axes & POSITION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007069 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
7070 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007071 }
7072 if (axes & TOUCH) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007073 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN,
7074 RAW_TOUCH_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007075 if (axes & MINOR) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007076 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN,
7077 RAW_TOUCH_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007078 }
7079 }
7080 if (axes & TOOL) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007081 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7082 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007083 if (axes & MINOR) {
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007084 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MIN,
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007085 RAW_TOOL_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007086 }
7087 }
7088 if (axes & ORIENTATION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007089 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_ORIENTATION, RAW_ORIENTATION_MIN,
7090 RAW_ORIENTATION_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007091 }
7092 if (axes & PRESSURE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007093 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_PRESSURE, RAW_PRESSURE_MIN,
7094 RAW_PRESSURE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007095 }
7096 if (axes & DISTANCE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007097 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_DISTANCE, RAW_DISTANCE_MIN,
7098 RAW_DISTANCE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007099 }
7100 if (axes & ID) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007101 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TRACKING_ID, RAW_ID_MIN, RAW_ID_MAX, 0,
7102 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007103 }
7104 if (axes & SLOT) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007105 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_SLOT, RAW_SLOT_MIN, RAW_SLOT_MAX, 0, 0);
7106 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007107 }
7108 if (axes & TOOL_TYPE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007109 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007110 }
7111}
7112
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007113void MultiTouchInputMapperTest::processPosition(MultiTouchInputMapper& mapper, int32_t x,
7114 int32_t y) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007115 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
7116 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007117}
7118
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007119void MultiTouchInputMapperTest::processTouchMajor(MultiTouchInputMapper& mapper,
7120 int32_t touchMajor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007121 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOUCH_MAJOR, touchMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007122}
7123
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007124void MultiTouchInputMapperTest::processTouchMinor(MultiTouchInputMapper& mapper,
7125 int32_t touchMinor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007126 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOUCH_MINOR, touchMinor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007127}
7128
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007129void MultiTouchInputMapperTest::processToolMajor(MultiTouchInputMapper& mapper, int32_t toolMajor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007130 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_WIDTH_MAJOR, toolMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007131}
7132
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007133void MultiTouchInputMapperTest::processToolMinor(MultiTouchInputMapper& mapper, int32_t toolMinor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007134 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_WIDTH_MINOR, toolMinor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007135}
7136
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007137void MultiTouchInputMapperTest::processOrientation(MultiTouchInputMapper& mapper,
7138 int32_t orientation) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007139 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_ORIENTATION, orientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007140}
7141
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007142void MultiTouchInputMapperTest::processPressure(MultiTouchInputMapper& mapper, int32_t pressure) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007143 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_PRESSURE, pressure);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007144}
7145
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007146void MultiTouchInputMapperTest::processDistance(MultiTouchInputMapper& mapper, int32_t distance) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007147 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_DISTANCE, distance);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007148}
7149
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007150void MultiTouchInputMapperTest::processId(MultiTouchInputMapper& mapper, int32_t id) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007151 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TRACKING_ID, id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007152}
7153
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007154void MultiTouchInputMapperTest::processSlot(MultiTouchInputMapper& mapper, int32_t slot) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007155 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_SLOT, slot);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007156}
7157
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007158void MultiTouchInputMapperTest::processToolType(MultiTouchInputMapper& mapper, int32_t toolType) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007159 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOOL_TYPE, toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007160}
7161
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007162void MultiTouchInputMapperTest::processKey(MultiTouchInputMapper& mapper, int32_t code,
7163 int32_t value) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007164 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007165}
7166
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00007167void MultiTouchInputMapperTest::processHidUsage(MultiTouchInputMapper& mapper, int32_t usageCode,
7168 int32_t value) {
7169 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, usageCode);
7170 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, value);
7171}
7172
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007173void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper& mapper) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007174 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_MT_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007175}
7176
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00007177void MultiTouchInputMapperTest::processSync(MultiTouchInputMapper& mapper, nsecs_t eventTime,
7178 nsecs_t readTime) {
7179 process(mapper, eventTime, readTime, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007180}
7181
Michael Wrightd02c5b62014-02-10 15:10:22 -08007182TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackingIds) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007183 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007184 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007185 prepareAxes(POSITION);
7186 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007187 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007188
arthurhungdcef2dc2020-08-11 14:47:50 +08007189 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007190
7191 NotifyMotionArgs motionArgs;
7192
7193 // Two fingers down at once.
7194 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7195 processPosition(mapper, x1, y1);
7196 processMTSync(mapper);
7197 processPosition(mapper, x2, y2);
7198 processMTSync(mapper);
7199 processSync(mapper);
7200
7201 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7202 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7203 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7204 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7205 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7206 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
7207 ASSERT_EQ(0, motionArgs.flags);
7208 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7209 ASSERT_EQ(0, motionArgs.buttonState);
7210 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007211 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007212 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007213 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007214 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7215 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7216 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7217 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7218 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7219
7220 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7221 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7222 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7223 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7224 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007225 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007226 ASSERT_EQ(0, motionArgs.flags);
7227 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7228 ASSERT_EQ(0, motionArgs.buttonState);
7229 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007230 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007231 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007232 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007233 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007234 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007235 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7236 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7237 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7238 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7239 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7240 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7241 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7242
7243 // Move.
7244 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7245 processPosition(mapper, x1, y1);
7246 processMTSync(mapper);
7247 processPosition(mapper, x2, y2);
7248 processMTSync(mapper);
7249 processSync(mapper);
7250
7251 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7252 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7253 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7254 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7255 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7256 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7257 ASSERT_EQ(0, motionArgs.flags);
7258 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7259 ASSERT_EQ(0, motionArgs.buttonState);
7260 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007261 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007262 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007263 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007264 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007265 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007266 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7267 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7268 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7269 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7270 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7271 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7272 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7273
7274 // First finger up.
7275 x2 += 15; y2 -= 20;
7276 processPosition(mapper, x2, y2);
7277 processMTSync(mapper);
7278 processSync(mapper);
7279
7280 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7281 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7282 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7283 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7284 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007285 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007286 ASSERT_EQ(0, motionArgs.flags);
7287 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7288 ASSERT_EQ(0, motionArgs.buttonState);
7289 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007290 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007291 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007292 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007293 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007294 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007295 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7296 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7297 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7298 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7299 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7300 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7301 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7302
7303 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7304 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7305 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7306 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7307 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7308 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7309 ASSERT_EQ(0, motionArgs.flags);
7310 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7311 ASSERT_EQ(0, motionArgs.buttonState);
7312 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007313 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007314 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007315 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007316 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7317 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7318 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7319 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7320 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7321
7322 // Move.
7323 x2 += 20; y2 -= 25;
7324 processPosition(mapper, x2, y2);
7325 processMTSync(mapper);
7326 processSync(mapper);
7327
7328 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7329 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7330 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7331 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7332 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7333 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7334 ASSERT_EQ(0, motionArgs.flags);
7335 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7336 ASSERT_EQ(0, motionArgs.buttonState);
7337 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007338 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007339 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007340 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007341 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7342 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7343 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7344 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7345 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7346
7347 // New finger down.
7348 int32_t x3 = 700, y3 = 300;
7349 processPosition(mapper, x2, y2);
7350 processMTSync(mapper);
7351 processPosition(mapper, x3, y3);
7352 processMTSync(mapper);
7353 processSync(mapper);
7354
7355 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7356 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7357 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7358 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7359 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007360 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007361 ASSERT_EQ(0, motionArgs.flags);
7362 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7363 ASSERT_EQ(0, motionArgs.buttonState);
7364 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007365 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007366 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007367 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007368 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007369 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007370 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7371 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7372 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7373 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7374 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7375 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7376 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7377
7378 // Second finger up.
7379 x3 += 30; y3 -= 20;
7380 processPosition(mapper, x3, y3);
7381 processMTSync(mapper);
7382 processSync(mapper);
7383
7384 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7385 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7386 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7387 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7388 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007389 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007390 ASSERT_EQ(0, motionArgs.flags);
7391 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7392 ASSERT_EQ(0, motionArgs.buttonState);
7393 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007394 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007395 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007396 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007397 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007398 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007399 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7400 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7401 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7402 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7403 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7404 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7405 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7406
7407 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7408 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7409 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7410 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7411 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7412 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7413 ASSERT_EQ(0, motionArgs.flags);
7414 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7415 ASSERT_EQ(0, motionArgs.buttonState);
7416 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007417 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007418 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007419 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007420 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7421 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7422 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7423 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7424 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7425
7426 // Last finger up.
7427 processMTSync(mapper);
7428 processSync(mapper);
7429
7430 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7431 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7432 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7433 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7434 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7435 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
7436 ASSERT_EQ(0, motionArgs.flags);
7437 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7438 ASSERT_EQ(0, motionArgs.buttonState);
7439 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007440 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007441 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007442 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007443 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7444 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7445 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7446 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7447 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7448
7449 // Should not have sent any more keys or motions.
7450 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7451 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7452}
7453
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007454TEST_F(MultiTouchInputMapperTest, AxisResolution_IsPopulated) {
7455 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007456 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007457
7458 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, /*flat*/ 0,
7459 /*fuzz*/ 0, /*resolution*/ 10);
7460 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, /*flat*/ 0,
7461 /*fuzz*/ 0, /*resolution*/ 11);
7462 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX,
7463 /*flat*/ 0, /*fuzz*/ 0, /*resolution*/ 12);
7464 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX,
7465 /*flat*/ 0, /*fuzz*/ 0, /*resolution*/ 13);
7466 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7467 /*flat*/ 0, /*flat*/ 0, /*resolution*/ 14);
7468 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7469 /*flat*/ 0, /*flat*/ 0, /*resolution*/ 15);
7470
Arpit Singha8c236b2023-04-25 13:56:05 +00007471 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007472
7473 // X and Y axes
7474 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_X, 10 / X_PRECISION);
7475 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_Y, 11 / Y_PRECISION);
7476 // Touch major and minor
7477 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOUCH_MAJOR, 12 * GEOMETRIC_SCALE);
7478 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOUCH_MINOR, 13 * GEOMETRIC_SCALE);
7479 // Tool major and minor
7480 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOOL_MAJOR, 14 * GEOMETRIC_SCALE);
7481 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOOL_MINOR, 15 * GEOMETRIC_SCALE);
7482}
7483
7484TEST_F(MultiTouchInputMapperTest, TouchMajorAndMinorAxes_DoNotAppearIfNotSupported) {
7485 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007486 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007487
7488 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, /*flat*/ 0,
7489 /*fuzz*/ 0, /*resolution*/ 10);
7490 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, /*flat*/ 0,
7491 /*fuzz*/ 0, /*resolution*/ 11);
7492
7493 // We do not add ABS_MT_TOUCH_MAJOR / MINOR or ABS_MT_WIDTH_MAJOR / MINOR axes
7494
Arpit Singha8c236b2023-04-25 13:56:05 +00007495 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007496
7497 // Touch major and minor
7498 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOUCH_MAJOR);
7499 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOUCH_MINOR);
7500 // Tool major and minor
7501 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOOL_MAJOR);
7502 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOOL_MINOR);
7503}
7504
Michael Wrightd02c5b62014-02-10 15:10:22 -08007505TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingIds) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007506 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007507 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007508 prepareAxes(POSITION | ID);
7509 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007510 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007511
arthurhungdcef2dc2020-08-11 14:47:50 +08007512 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007513
7514 NotifyMotionArgs motionArgs;
7515
7516 // Two fingers down at once.
7517 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7518 processPosition(mapper, x1, y1);
7519 processId(mapper, 1);
7520 processMTSync(mapper);
7521 processPosition(mapper, x2, y2);
7522 processId(mapper, 2);
7523 processMTSync(mapper);
7524 processSync(mapper);
7525
7526 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7527 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007528 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007529 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007530 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007531 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7532 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7533
7534 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007535 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007536 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007537 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007538 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007539 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007540 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007541 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7542 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7543 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7544 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7545
7546 // Move.
7547 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7548 processPosition(mapper, x1, y1);
7549 processId(mapper, 1);
7550 processMTSync(mapper);
7551 processPosition(mapper, x2, y2);
7552 processId(mapper, 2);
7553 processMTSync(mapper);
7554 processSync(mapper);
7555
7556 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7557 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007558 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007559 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007560 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007561 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007562 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007563 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7564 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7565 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7566 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7567
7568 // First finger up.
7569 x2 += 15; y2 -= 20;
7570 processPosition(mapper, x2, y2);
7571 processId(mapper, 2);
7572 processMTSync(mapper);
7573 processSync(mapper);
7574
7575 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007576 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007577 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007578 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007579 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007580 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007581 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007582 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7583 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7584 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7585 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7586
7587 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7588 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007589 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007590 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007591 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007592 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7593 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7594
7595 // Move.
7596 x2 += 20; y2 -= 25;
7597 processPosition(mapper, x2, y2);
7598 processId(mapper, 2);
7599 processMTSync(mapper);
7600 processSync(mapper);
7601
7602 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7603 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007604 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007605 ASSERT_EQ(1, 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_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7608 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7609
7610 // New finger down.
7611 int32_t x3 = 700, y3 = 300;
7612 processPosition(mapper, x2, y2);
7613 processId(mapper, 2);
7614 processMTSync(mapper);
7615 processPosition(mapper, x3, y3);
7616 processId(mapper, 3);
7617 processMTSync(mapper);
7618 processSync(mapper);
7619
7620 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007621 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007622 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007623 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007624 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007625 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007626 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007627 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7628 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7629 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7630 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7631
7632 // Second finger up.
7633 x3 += 30; y3 -= 20;
7634 processPosition(mapper, x3, y3);
7635 processId(mapper, 3);
7636 processMTSync(mapper);
7637 processSync(mapper);
7638
7639 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007640 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007641 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007642 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007643 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007644 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007645 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007646 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7647 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7648 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7649 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7650
7651 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7652 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007653 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007654 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007655 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007656 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7657 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7658
7659 // Last finger up.
7660 processMTSync(mapper);
7661 processSync(mapper);
7662
7663 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7664 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007665 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007666 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007667 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007668 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7669 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7670
7671 // Should not have sent any more keys or motions.
7672 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7673 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7674}
7675
7676TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithSlots) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007677 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007678 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007679 prepareAxes(POSITION | ID | SLOT);
7680 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007681 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007682
arthurhungdcef2dc2020-08-11 14:47:50 +08007683 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007684
7685 NotifyMotionArgs motionArgs;
7686
7687 // Two fingers down at once.
7688 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7689 processPosition(mapper, x1, y1);
7690 processId(mapper, 1);
7691 processSlot(mapper, 1);
7692 processPosition(mapper, x2, y2);
7693 processId(mapper, 2);
7694 processSync(mapper);
7695
7696 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7697 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007698 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007699 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007700 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007701 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7702 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7703
7704 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007705 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007706 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007707 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007708 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007709 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007710 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007711 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7712 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7713 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7714 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7715
7716 // Move.
7717 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7718 processSlot(mapper, 0);
7719 processPosition(mapper, x1, y1);
7720 processSlot(mapper, 1);
7721 processPosition(mapper, x2, y2);
7722 processSync(mapper);
7723
7724 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7725 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007726 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007727 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007728 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007729 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007730 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007731 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7732 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7733 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7734 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7735
7736 // First finger up.
7737 x2 += 15; y2 -= 20;
7738 processSlot(mapper, 0);
7739 processId(mapper, -1);
7740 processSlot(mapper, 1);
7741 processPosition(mapper, x2, y2);
7742 processSync(mapper);
7743
7744 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007745 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007746 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007747 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007748 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007749 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007750 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007751 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7752 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7753 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7754 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7755
7756 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7757 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007758 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007759 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007760 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007761 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7762 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7763
7764 // Move.
7765 x2 += 20; y2 -= 25;
7766 processPosition(mapper, x2, y2);
7767 processSync(mapper);
7768
7769 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7770 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007771 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007772 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007773 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007774 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7775 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7776
7777 // New finger down.
7778 int32_t x3 = 700, y3 = 300;
7779 processPosition(mapper, x2, y2);
7780 processSlot(mapper, 0);
7781 processId(mapper, 3);
7782 processPosition(mapper, x3, y3);
7783 processSync(mapper);
7784
7785 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007786 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007787 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007788 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007789 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007790 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007791 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007792 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7793 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7794 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7795 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7796
7797 // Second finger up.
7798 x3 += 30; y3 -= 20;
7799 processSlot(mapper, 1);
7800 processId(mapper, -1);
7801 processSlot(mapper, 0);
7802 processPosition(mapper, x3, y3);
7803 processSync(mapper);
7804
7805 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007806 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007807 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007808 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007809 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007810 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007811 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007812 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7813 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7814 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7815 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7816
7817 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7818 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007819 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007820 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007821 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007822 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7823 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7824
7825 // Last finger up.
7826 processId(mapper, -1);
7827 processSync(mapper);
7828
7829 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7830 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007831 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007832 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007833 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007834 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7835 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7836
7837 // Should not have sent any more keys or motions.
7838 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7839 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7840}
7841
7842TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007843 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007844 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007845 prepareAxes(POSITION | TOUCH | TOOL | PRESSURE | ORIENTATION | ID | MINOR | DISTANCE);
Arpit Singha8c236b2023-04-25 13:56:05 +00007846 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007847
7848 // These calculations are based on the input device calibration documentation.
7849 int32_t rawX = 100;
7850 int32_t rawY = 200;
7851 int32_t rawTouchMajor = 7;
7852 int32_t rawTouchMinor = 6;
7853 int32_t rawToolMajor = 9;
7854 int32_t rawToolMinor = 8;
7855 int32_t rawPressure = 11;
7856 int32_t rawDistance = 0;
7857 int32_t rawOrientation = 3;
7858 int32_t id = 5;
7859
7860 float x = toDisplayX(rawX);
7861 float y = toDisplayY(rawY);
7862 float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
7863 float size = avg(rawTouchMajor, rawTouchMinor) / RAW_TOUCH_MAX;
7864 float toolMajor = float(rawToolMajor) * GEOMETRIC_SCALE;
7865 float toolMinor = float(rawToolMinor) * GEOMETRIC_SCALE;
7866 float touchMajor = float(rawTouchMajor) * GEOMETRIC_SCALE;
7867 float touchMinor = float(rawTouchMinor) * GEOMETRIC_SCALE;
7868 float orientation = float(rawOrientation) / RAW_ORIENTATION_MAX * M_PI_2;
7869 float distance = float(rawDistance);
7870
7871 processPosition(mapper, rawX, rawY);
7872 processTouchMajor(mapper, rawTouchMajor);
7873 processTouchMinor(mapper, rawTouchMinor);
7874 processToolMajor(mapper, rawToolMajor);
7875 processToolMinor(mapper, rawToolMinor);
7876 processPressure(mapper, rawPressure);
7877 processOrientation(mapper, rawOrientation);
7878 processDistance(mapper, rawDistance);
7879 processId(mapper, id);
7880 processMTSync(mapper);
7881 processSync(mapper);
7882
7883 NotifyMotionArgs args;
7884 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7885 ASSERT_EQ(0, args.pointerProperties[0].id);
7886 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7887 x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor,
7888 orientation, distance));
Prabir Pradhan9a53b552024-06-04 02:59:40 +00007889 ASSERT_EQ(args.flags, AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007890}
7891
7892TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_GeometricCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007893 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007894 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007895 prepareAxes(POSITION | TOUCH | TOOL | MINOR);
7896 addConfigurationProperty("touch.size.calibration", "geometric");
Arpit Singha8c236b2023-04-25 13:56:05 +00007897 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007898
7899 // These calculations are based on the input device calibration documentation.
7900 int32_t rawX = 100;
7901 int32_t rawY = 200;
7902 int32_t rawTouchMajor = 140;
7903 int32_t rawTouchMinor = 120;
7904 int32_t rawToolMajor = 180;
7905 int32_t rawToolMinor = 160;
7906
7907 float x = toDisplayX(rawX);
7908 float y = toDisplayY(rawY);
7909 float size = avg(rawTouchMajor, rawTouchMinor) / RAW_TOUCH_MAX;
7910 float toolMajor = float(rawToolMajor) * GEOMETRIC_SCALE;
7911 float toolMinor = float(rawToolMinor) * GEOMETRIC_SCALE;
7912 float touchMajor = float(rawTouchMajor) * GEOMETRIC_SCALE;
7913 float touchMinor = float(rawTouchMinor) * GEOMETRIC_SCALE;
7914
7915 processPosition(mapper, rawX, rawY);
7916 processTouchMajor(mapper, rawTouchMajor);
7917 processTouchMinor(mapper, rawTouchMinor);
7918 processToolMajor(mapper, rawToolMajor);
7919 processToolMinor(mapper, rawToolMinor);
7920 processMTSync(mapper);
7921 processSync(mapper);
7922
7923 NotifyMotionArgs args;
7924 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7925 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7926 x, y, 1.0f, size, touchMajor, touchMinor, toolMajor, toolMinor, 0, 0));
7927}
7928
7929TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_SummedLinearCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007930 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007931 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007932 prepareAxes(POSITION | TOUCH | TOOL);
7933 addConfigurationProperty("touch.size.calibration", "diameter");
7934 addConfigurationProperty("touch.size.scale", "10");
7935 addConfigurationProperty("touch.size.bias", "160");
7936 addConfigurationProperty("touch.size.isSummed", "1");
Arpit Singha8c236b2023-04-25 13:56:05 +00007937 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007938
7939 // These calculations are based on the input device calibration documentation.
7940 // Note: We only provide a single common touch/tool value because the device is assumed
7941 // not to emit separate values for each pointer (isSummed = 1).
7942 int32_t rawX = 100;
7943 int32_t rawY = 200;
7944 int32_t rawX2 = 150;
7945 int32_t rawY2 = 250;
7946 int32_t rawTouchMajor = 5;
7947 int32_t rawToolMajor = 8;
7948
7949 float x = toDisplayX(rawX);
7950 float y = toDisplayY(rawY);
7951 float x2 = toDisplayX(rawX2);
7952 float y2 = toDisplayY(rawY2);
7953 float size = float(rawTouchMajor) / 2 / RAW_TOUCH_MAX;
7954 float touch = float(rawTouchMajor) / 2 * 10.0f + 160.0f;
7955 float tool = float(rawToolMajor) / 2 * 10.0f + 160.0f;
7956
7957 processPosition(mapper, rawX, rawY);
7958 processTouchMajor(mapper, rawTouchMajor);
7959 processToolMajor(mapper, rawToolMajor);
7960 processMTSync(mapper);
7961 processPosition(mapper, rawX2, rawY2);
7962 processTouchMajor(mapper, rawTouchMajor);
7963 processToolMajor(mapper, rawToolMajor);
7964 processMTSync(mapper);
7965 processSync(mapper);
7966
7967 NotifyMotionArgs args;
7968 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7969 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
7970
7971 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007972 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007973 ASSERT_EQ(size_t(2), args.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007974 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7975 x, y, 1.0f, size, touch, touch, tool, tool, 0, 0));
7976 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[1],
7977 x2, y2, 1.0f, size, touch, touch, tool, tool, 0, 0));
7978}
7979
7980TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_AreaCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007981 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007982 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007983 prepareAxes(POSITION | TOUCH | TOOL);
7984 addConfigurationProperty("touch.size.calibration", "area");
7985 addConfigurationProperty("touch.size.scale", "43");
7986 addConfigurationProperty("touch.size.bias", "3");
Arpit Singha8c236b2023-04-25 13:56:05 +00007987 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007988
7989 // These calculations are based on the input device calibration documentation.
7990 int32_t rawX = 100;
7991 int32_t rawY = 200;
7992 int32_t rawTouchMajor = 5;
7993 int32_t rawToolMajor = 8;
7994
7995 float x = toDisplayX(rawX);
7996 float y = toDisplayY(rawY);
7997 float size = float(rawTouchMajor) / RAW_TOUCH_MAX;
7998 float touch = sqrtf(rawTouchMajor) * 43.0f + 3.0f;
7999 float tool = sqrtf(rawToolMajor) * 43.0f + 3.0f;
8000
8001 processPosition(mapper, rawX, rawY);
8002 processTouchMajor(mapper, rawTouchMajor);
8003 processToolMajor(mapper, rawToolMajor);
8004 processMTSync(mapper);
8005 processSync(mapper);
8006
8007 NotifyMotionArgs args;
8008 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8009 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8010 x, y, 1.0f, size, touch, touch, tool, tool, 0, 0));
8011}
8012
8013TEST_F(MultiTouchInputMapperTest, Process_PressureAxis_AmplitudeCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008014 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008015 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008016 prepareAxes(POSITION | PRESSURE);
8017 addConfigurationProperty("touch.pressure.calibration", "amplitude");
8018 addConfigurationProperty("touch.pressure.scale", "0.01");
Arpit Singha8c236b2023-04-25 13:56:05 +00008019 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008020
Michael Wrightaa449c92017-12-13 21:21:43 +00008021 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +00008022 mapper.populateDeviceInfo(info);
Michael Wrightaa449c92017-12-13 21:21:43 +00008023 ASSERT_NO_FATAL_FAILURE(assertMotionRange(info,
8024 AINPUT_MOTION_RANGE_PRESSURE, AINPUT_SOURCE_TOUCHSCREEN,
8025 0.0f, RAW_PRESSURE_MAX * 0.01, 0.0f, 0.0f));
8026
Michael Wrightd02c5b62014-02-10 15:10:22 -08008027 // These calculations are based on the input device calibration documentation.
8028 int32_t rawX = 100;
8029 int32_t rawY = 200;
8030 int32_t rawPressure = 60;
8031
8032 float x = toDisplayX(rawX);
8033 float y = toDisplayY(rawY);
8034 float pressure = float(rawPressure) * 0.01f;
8035
8036 processPosition(mapper, rawX, rawY);
8037 processPressure(mapper, rawPressure);
8038 processMTSync(mapper);
8039 processSync(mapper);
8040
8041 NotifyMotionArgs args;
8042 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8043 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8044 x, y, pressure, 0, 0, 0, 0, 0, 0, 0));
8045}
8046
8047TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllButtons) {
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 | ID | SLOT);
Arpit Singha8c236b2023-04-25 13:56:05 +00008051 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008052
8053 NotifyMotionArgs motionArgs;
8054 NotifyKeyArgs keyArgs;
8055
8056 processId(mapper, 1);
8057 processPosition(mapper, 100, 200);
8058 processSync(mapper);
8059 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8060 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8061 ASSERT_EQ(0, motionArgs.buttonState);
8062
8063 // press BTN_LEFT, release BTN_LEFT
8064 processKey(mapper, BTN_LEFT, 1);
8065 processSync(mapper);
8066 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8067 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
8068 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
8069
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008070 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8071 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8072 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
8073
Michael Wrightd02c5b62014-02-10 15:10:22 -08008074 processKey(mapper, BTN_LEFT, 0);
8075 processSync(mapper);
8076 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008077 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008078 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008079
8080 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008081 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008082 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008083
8084 // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
8085 processKey(mapper, BTN_RIGHT, 1);
8086 processKey(mapper, BTN_MIDDLE, 1);
8087 processSync(mapper);
8088 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8089 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
8090 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
8091 motionArgs.buttonState);
8092
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008093 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8094 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8095 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
8096
8097 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8098 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8099 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
8100 motionArgs.buttonState);
8101
Michael Wrightd02c5b62014-02-10 15:10:22 -08008102 processKey(mapper, BTN_RIGHT, 0);
8103 processSync(mapper);
8104 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008105 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008106 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008107
8108 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008109 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008110 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008111
8112 processKey(mapper, BTN_MIDDLE, 0);
8113 processSync(mapper);
8114 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008115 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008116 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008117
8118 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008119 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008120 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008121
8122 // press BTN_BACK, release BTN_BACK
8123 processKey(mapper, BTN_BACK, 1);
8124 processSync(mapper);
8125 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8126 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8127 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008128
Michael Wrightd02c5b62014-02-10 15:10:22 -08008129 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008130 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008131 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
8132
8133 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8134 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8135 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008136
8137 processKey(mapper, BTN_BACK, 0);
8138 processSync(mapper);
8139 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008140 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008141 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008142
8143 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008144 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008145 ASSERT_EQ(0, motionArgs.buttonState);
8146
Michael Wrightd02c5b62014-02-10 15:10:22 -08008147 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8148 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8149 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
8150
8151 // press BTN_SIDE, release BTN_SIDE
8152 processKey(mapper, BTN_SIDE, 1);
8153 processSync(mapper);
8154 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8155 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8156 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008157
Michael Wrightd02c5b62014-02-10 15:10:22 -08008158 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008159 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008160 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
8161
8162 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8163 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8164 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008165
8166 processKey(mapper, BTN_SIDE, 0);
8167 processSync(mapper);
8168 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008169 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008170 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008171
8172 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008173 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008174 ASSERT_EQ(0, motionArgs.buttonState);
8175
Michael Wrightd02c5b62014-02-10 15:10:22 -08008176 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8177 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8178 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
8179
8180 // press BTN_FORWARD, release BTN_FORWARD
8181 processKey(mapper, BTN_FORWARD, 1);
8182 processSync(mapper);
8183 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8184 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8185 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008186
Michael Wrightd02c5b62014-02-10 15:10:22 -08008187 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008188 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008189 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
8190
8191 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8192 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8193 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008194
8195 processKey(mapper, BTN_FORWARD, 0);
8196 processSync(mapper);
8197 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008198 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008199 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008200
8201 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008202 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008203 ASSERT_EQ(0, motionArgs.buttonState);
8204
Michael Wrightd02c5b62014-02-10 15:10:22 -08008205 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8206 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8207 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
8208
8209 // press BTN_EXTRA, release BTN_EXTRA
8210 processKey(mapper, BTN_EXTRA, 1);
8211 processSync(mapper);
8212 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8213 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8214 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008215
Michael Wrightd02c5b62014-02-10 15:10:22 -08008216 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008217 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008218 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
8219
8220 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8221 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8222 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008223
8224 processKey(mapper, BTN_EXTRA, 0);
8225 processSync(mapper);
8226 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008227 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008228 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008229
8230 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008231 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008232 ASSERT_EQ(0, motionArgs.buttonState);
8233
Michael Wrightd02c5b62014-02-10 15:10:22 -08008234 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8235 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8236 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
8237
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008238 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
8239
Michael Wrightd02c5b62014-02-10 15:10:22 -08008240 // press BTN_STYLUS, release BTN_STYLUS
8241 processKey(mapper, BTN_STYLUS, 1);
8242 processSync(mapper);
8243 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8244 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008245 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
8246
8247 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8248 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8249 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008250
8251 processKey(mapper, BTN_STYLUS, 0);
8252 processSync(mapper);
8253 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008254 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008255 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008256
8257 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008258 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008259 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008260
8261 // press BTN_STYLUS2, release BTN_STYLUS2
8262 processKey(mapper, BTN_STYLUS2, 1);
8263 processSync(mapper);
8264 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8265 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008266 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
8267
8268 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8269 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8270 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008271
8272 processKey(mapper, BTN_STYLUS2, 0);
8273 processSync(mapper);
8274 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008275 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008276 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008277
8278 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008279 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008280 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008281
8282 // release touch
8283 processId(mapper, -1);
8284 processSync(mapper);
8285 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8286 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8287 ASSERT_EQ(0, motionArgs.buttonState);
8288}
8289
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008290TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleMappedStylusButtons) {
8291 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008292 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008293 prepareAxes(POSITION | ID | SLOT);
Arpit Singha8c236b2023-04-25 13:56:05 +00008294 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008295
8296 mFakeEventHub->addKey(EVENTHUB_ID, BTN_A, 0, AKEYCODE_STYLUS_BUTTON_PRIMARY, 0);
8297 mFakeEventHub->addKey(EVENTHUB_ID, 0, 0xabcd, AKEYCODE_STYLUS_BUTTON_SECONDARY, 0);
8298
8299 // Touch down.
8300 processId(mapper, 1);
8301 processPosition(mapper, 100, 200);
8302 processSync(mapper);
8303 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8304 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithButtonState(0))));
8305
8306 // Press and release button mapped to the primary stylus button.
8307 processKey(mapper, BTN_A, 1);
8308 processSync(mapper);
8309 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8310 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
8311 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
8312 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8313 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
8314 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
8315
8316 processKey(mapper, BTN_A, 0);
8317 processSync(mapper);
8318 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8319 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithButtonState(0))));
8320 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8321 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
8322
8323 // Press and release the HID usage mapped to the secondary stylus button.
8324 processHidUsage(mapper, 0xabcd, 1);
8325 processSync(mapper);
8326 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8327 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
8328 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY))));
8329 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8330 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
8331 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY))));
8332
8333 processHidUsage(mapper, 0xabcd, 0);
8334 processSync(mapper);
8335 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8336 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithButtonState(0))));
8337 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8338 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
8339
8340 // Release touch.
8341 processId(mapper, -1);
8342 processSync(mapper);
8343 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8344 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
8345}
8346
Michael Wrightd02c5b62014-02-10 15:10:22 -08008347TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008348 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008349 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008350 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00008351 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008352
8353 NotifyMotionArgs motionArgs;
8354
8355 // default tool type is finger
8356 processId(mapper, 1);
8357 processPosition(mapper, 100, 200);
8358 processSync(mapper);
8359 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8360 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008361 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008362
8363 // eraser
8364 processKey(mapper, BTN_TOOL_RUBBER, 1);
8365 processSync(mapper);
8366 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8367 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008368 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008369
8370 // stylus
8371 processKey(mapper, BTN_TOOL_RUBBER, 0);
8372 processKey(mapper, BTN_TOOL_PEN, 1);
8373 processSync(mapper);
8374 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8375 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008376 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008377
8378 // brush
8379 processKey(mapper, BTN_TOOL_PEN, 0);
8380 processKey(mapper, BTN_TOOL_BRUSH, 1);
8381 processSync(mapper);
8382 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8383 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008384 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008385
8386 // pencil
8387 processKey(mapper, BTN_TOOL_BRUSH, 0);
8388 processKey(mapper, BTN_TOOL_PENCIL, 1);
8389 processSync(mapper);
8390 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8391 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008392 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008393
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08008394 // air-brush
Michael Wrightd02c5b62014-02-10 15:10:22 -08008395 processKey(mapper, BTN_TOOL_PENCIL, 0);
8396 processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
8397 processSync(mapper);
8398 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8399 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008400 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008401
8402 // mouse
8403 processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
8404 processKey(mapper, BTN_TOOL_MOUSE, 1);
8405 processSync(mapper);
8406 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8407 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008408 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008409
8410 // lens
8411 processKey(mapper, BTN_TOOL_MOUSE, 0);
8412 processKey(mapper, BTN_TOOL_LENS, 1);
8413 processSync(mapper);
8414 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8415 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008416 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008417
8418 // double-tap
8419 processKey(mapper, BTN_TOOL_LENS, 0);
8420 processKey(mapper, BTN_TOOL_DOUBLETAP, 1);
8421 processSync(mapper);
8422 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8423 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008424 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008425
8426 // triple-tap
8427 processKey(mapper, BTN_TOOL_DOUBLETAP, 0);
8428 processKey(mapper, BTN_TOOL_TRIPLETAP, 1);
8429 processSync(mapper);
8430 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8431 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008432 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008433
8434 // quad-tap
8435 processKey(mapper, BTN_TOOL_TRIPLETAP, 0);
8436 processKey(mapper, BTN_TOOL_QUADTAP, 1);
8437 processSync(mapper);
8438 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8439 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008440 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008441
8442 // finger
8443 processKey(mapper, BTN_TOOL_QUADTAP, 0);
8444 processKey(mapper, BTN_TOOL_FINGER, 1);
8445 processSync(mapper);
8446 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8447 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008448 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008449
8450 // stylus trumps finger
8451 processKey(mapper, BTN_TOOL_PEN, 1);
8452 processSync(mapper);
8453 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8454 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008455 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008456
8457 // eraser trumps stylus
8458 processKey(mapper, BTN_TOOL_RUBBER, 1);
8459 processSync(mapper);
8460 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8461 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008462 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008463
8464 // mouse trumps eraser
8465 processKey(mapper, BTN_TOOL_MOUSE, 1);
8466 processSync(mapper);
8467 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8468 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008469 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008470
8471 // MT tool type trumps BTN tool types: MT_TOOL_FINGER
8472 processToolType(mapper, MT_TOOL_FINGER); // this is the first time we send MT_TOOL_TYPE
8473 processSync(mapper);
8474 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8475 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008476 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008477
8478 // MT tool type trumps BTN tool types: MT_TOOL_PEN
8479 processToolType(mapper, MT_TOOL_PEN);
8480 processSync(mapper);
8481 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8482 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008483 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008484
8485 // back to default tool type
8486 processToolType(mapper, -1); // use a deliberately undefined tool type, for testing
8487 processKey(mapper, BTN_TOOL_MOUSE, 0);
8488 processKey(mapper, BTN_TOOL_RUBBER, 0);
8489 processKey(mapper, BTN_TOOL_PEN, 0);
8490 processKey(mapper, BTN_TOOL_FINGER, 0);
8491 processSync(mapper);
8492 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8493 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008494 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008495}
8496
8497TEST_F(MultiTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008498 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008499 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008500 prepareAxes(POSITION | ID | SLOT);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008501 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00008502 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008503
8504 NotifyMotionArgs motionArgs;
8505
8506 // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0
8507 processId(mapper, 1);
8508 processPosition(mapper, 100, 200);
8509 processSync(mapper);
8510 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8511 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8512 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8513 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8514
8515 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8516 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8517 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8518 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8519
8520 // move a little
8521 processPosition(mapper, 150, 250);
8522 processSync(mapper);
8523 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8524 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8525 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8526 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8527
8528 // down when BTN_TOUCH is pressed, pressure defaults to 1
8529 processKey(mapper, BTN_TOUCH, 1);
8530 processSync(mapper);
8531 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8532 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8533 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8534 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8535
8536 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8537 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8538 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8539 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8540
8541 // up when BTN_TOUCH is released, hover restored
8542 processKey(mapper, BTN_TOUCH, 0);
8543 processSync(mapper);
8544 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8545 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8546 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8547 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8548
8549 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8550 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8551 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8552 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8553
8554 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8555 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8556 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8557 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8558
8559 // exit hover when pointer goes away
8560 processId(mapper, -1);
8561 processSync(mapper);
8562 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8563 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8564 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8565 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8566}
8567
8568TEST_F(MultiTouchInputMapperTest, Process_WhenAbsMTPressureIsPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008569 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008570 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008571 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00008572 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008573
8574 NotifyMotionArgs motionArgs;
8575
8576 // initially hovering because pressure is 0
8577 processId(mapper, 1);
8578 processPosition(mapper, 100, 200);
8579 processPressure(mapper, 0);
8580 processSync(mapper);
8581 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8582 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8583 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8584 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8585
8586 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8587 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8588 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8589 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8590
8591 // move a little
8592 processPosition(mapper, 150, 250);
8593 processSync(mapper);
8594 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8595 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8596 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8597 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8598
8599 // down when pressure becomes non-zero
8600 processPressure(mapper, RAW_PRESSURE_MAX);
8601 processSync(mapper);
8602 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8603 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8604 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8605 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8606
8607 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8608 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8609 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8610 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8611
8612 // up when pressure becomes 0, hover restored
8613 processPressure(mapper, 0);
8614 processSync(mapper);
8615 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8616 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8617 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8618 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8619
8620 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8621 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8622 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8623 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8624
8625 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8626 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8627 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8628 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8629
8630 // exit hover when pointer goes away
8631 processId(mapper, -1);
8632 processSync(mapper);
8633 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8634 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8635 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8636 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8637}
8638
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008639/**
8640 * Set the input device port <--> display port associations, and check that the
8641 * events are routed to the display that matches the display port.
8642 * This can be checked by looking at the displayId of the resulting NotifyMotionArgs.
8643 */
8644TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayPort) {
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008645 const std::string usb2 = "USB2";
8646 const uint8_t hdmi1 = 0;
8647 const uint8_t hdmi2 = 1;
8648 const std::string secondaryUniqueId = "uniqueId2";
Michael Wrightfe3de7d2020-07-02 19:05:30 +01008649 constexpr ViewportType type = ViewportType::EXTERNAL;
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008650
8651 addConfigurationProperty("touch.deviceType", "touchScreen");
8652 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008653 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008654
8655 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
8656 mFakePolicy->addInputPortAssociation(usb2, hdmi2);
8657
8658 // We are intentionally not adding the viewport for display 1 yet. Since the port association
8659 // for this input device is specified, and the matching viewport is not present,
8660 // the input device should be disabled (at the mapper level).
8661
8662 // Add viewport for display 2 on hdmi2
8663 prepareSecondaryDisplay(type, hdmi2);
8664 // Send a touch event
8665 processPosition(mapper, 100, 100);
8666 processSync(mapper);
8667 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
8668
8669 // Add viewport for display 1 on hdmi1
Michael Wrighta9cf4192022-12-01 23:46:39 +00008670 prepareDisplay(ui::ROTATION_0, hdmi1);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008671 // Send a touch event again
8672 processPosition(mapper, 100, 100);
8673 processSync(mapper);
8674
8675 NotifyMotionArgs args;
8676 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8677 ASSERT_EQ(DISPLAY_ID, args.displayId);
8678}
Michael Wrightd02c5b62014-02-10 15:10:22 -08008679
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008680TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayUniqueId) {
8681 addConfigurationProperty("touch.deviceType", "touchScreen");
8682 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008683 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008684
8685 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID);
8686
Michael Wrighta9cf4192022-12-01 23:46:39 +00008687 prepareDisplay(ui::ROTATION_0);
8688 prepareVirtualDisplay(ui::ROTATION_0);
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008689
8690 // Send a touch event
8691 processPosition(mapper, 100, 100);
8692 processSync(mapper);
8693
8694 NotifyMotionArgs args;
8695 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8696 ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId);
8697}
8698
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008699TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01008700 prepareSecondaryDisplay(ViewportType::EXTERNAL);
Garfield Tan888a6a42020-01-09 11:39:16 -08008701
Michael Wrighta9cf4192022-12-01 23:46:39 +00008702 prepareDisplay(ui::ROTATION_0);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008703 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008704 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008705
Josep del Río2d8c79a2023-01-23 19:33:50 +00008706 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008707
8708 NotifyMotionArgs motionArgs;
8709 processPosition(mapper, 100, 100);
8710 processSync(mapper);
8711
8712 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8713 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008714 ASSERT_EQ(ui::LogicalDisplayId::INVALID, motionArgs.displayId);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008715}
8716
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008717/**
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008718 * Ensure that the readTime is set to the SYN_REPORT value when processing touch events.
8719 */
8720TEST_F(MultiTouchInputMapperTest, Process_SendsReadTime) {
8721 addConfigurationProperty("touch.deviceType", "touchScreen");
8722 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008723 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008724
Michael Wrighta9cf4192022-12-01 23:46:39 +00008725 prepareDisplay(ui::ROTATION_0);
Harry Cutts33476232023-01-30 19:57:29 +00008726 process(mapper, 10, /*readTime=*/11, EV_ABS, ABS_MT_TRACKING_ID, 1);
8727 process(mapper, 15, /*readTime=*/16, EV_ABS, ABS_MT_POSITION_X, 100);
8728 process(mapper, 20, /*readTime=*/21, EV_ABS, ABS_MT_POSITION_Y, 100);
8729 process(mapper, 25, /*readTime=*/26, EV_SYN, SYN_REPORT, 0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008730
8731 NotifyMotionArgs args;
8732 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8733 ASSERT_EQ(26, args.readTime);
8734
Harry Cutts33476232023-01-30 19:57:29 +00008735 process(mapper, 30, /*readTime=*/31, EV_ABS, ABS_MT_POSITION_X, 110);
8736 process(mapper, 30, /*readTime=*/32, EV_ABS, ABS_MT_POSITION_Y, 220);
8737 process(mapper, 30, /*readTime=*/33, EV_SYN, SYN_REPORT, 0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008738
8739 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8740 ASSERT_EQ(33, args.readTime);
8741}
8742
8743/**
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008744 * When the viewport is not active (isActive=false), the touch mapper should be disabled and the
8745 * events should not be delivered to the listener.
8746 */
8747TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreDropped) {
8748 addConfigurationProperty("touch.deviceType", "touchScreen");
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008749 // Don't set touch.enableForInactiveViewport to verify the default behavior.
Michael Wrighta9cf4192022-12-01 23:46:39 +00008750 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008751 /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008752 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008753 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008754 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008755
8756 NotifyMotionArgs motionArgs;
8757 processPosition(mapper, 100, 100);
8758 processSync(mapper);
8759
8760 mFakeListener->assertNotifyMotionWasNotCalled();
8761}
8762
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008763/**
8764 * When the viewport is not active (isActive=false) and touch.enableForInactiveViewport is true,
8765 * the touch mapper can process the events and the events can be delivered to the listener.
8766 */
8767TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreProcessed) {
8768 addConfigurationProperty("touch.deviceType", "touchScreen");
8769 addConfigurationProperty("touch.enableForInactiveViewport", "1");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008770 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008771 /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008772 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008773 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008774 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008775
8776 NotifyMotionArgs motionArgs;
8777 processPosition(mapper, 100, 100);
8778 processSync(mapper);
8779
8780 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8781 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8782}
8783
Josh Thielene986aed2023-06-01 14:17:30 +00008784/**
8785 * When the viewport is deactivated (isActive transitions from true to false),
8786 * and touch.enableForInactiveViewport is false, touches prior to the transition
8787 * should be cancelled.
8788 */
Garfield Tanc734e4f2021-01-15 20:01:39 -08008789TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_AbortTouches) {
8790 addConfigurationProperty("touch.deviceType", "touchScreen");
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008791 addConfigurationProperty("touch.enableForInactiveViewport", "0");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008792 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008793 /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008794 std::optional<DisplayViewport> optionalDisplayViewport =
8795 mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
8796 ASSERT_TRUE(optionalDisplayViewport.has_value());
8797 DisplayViewport displayViewport = *optionalDisplayViewport;
8798
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008799 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008800 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008801 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Garfield Tanc734e4f2021-01-15 20:01:39 -08008802
8803 // Finger down
8804 int32_t x = 100, y = 100;
8805 processPosition(mapper, x, y);
8806 processSync(mapper);
8807
8808 NotifyMotionArgs motionArgs;
8809 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8810 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8811
8812 // Deactivate display viewport
8813 displayViewport.isActive = false;
8814 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008815 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008816
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008817 // The ongoing touch should be canceled immediately
8818 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8819 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
8820
8821 // Finger move is ignored
Garfield Tanc734e4f2021-01-15 20:01:39 -08008822 x += 10, y += 10;
8823 processPosition(mapper, x, y);
8824 processSync(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008825 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
Garfield Tanc734e4f2021-01-15 20:01:39 -08008826
8827 // Reactivate display viewport
8828 displayViewport.isActive = true;
8829 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008830 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008831
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008832 // Finger move again starts new gesture
Garfield Tanc734e4f2021-01-15 20:01:39 -08008833 x += 10, y += 10;
8834 processPosition(mapper, x, y);
8835 processSync(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008836 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8837 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008838}
8839
Josh Thielene986aed2023-06-01 14:17:30 +00008840/**
8841 * When the viewport is deactivated (isActive transitions from true to false),
8842 * and touch.enableForInactiveViewport is true, touches prior to the transition
8843 * should not be cancelled.
8844 */
8845TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_TouchesNotAborted) {
8846 addConfigurationProperty("touch.deviceType", "touchScreen");
8847 addConfigurationProperty("touch.enableForInactiveViewport", "1");
8848 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
8849 /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
8850 std::optional<DisplayViewport> optionalDisplayViewport =
8851 mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
8852 ASSERT_TRUE(optionalDisplayViewport.has_value());
8853 DisplayViewport displayViewport = *optionalDisplayViewport;
8854
8855 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8856 prepareAxes(POSITION);
8857 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
8858
8859 // Finger down
8860 int32_t x = 100, y = 100;
8861 processPosition(mapper, x, y);
8862 processSync(mapper);
8863 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8864 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
8865
8866 // Deactivate display viewport
8867 displayViewport.isActive = false;
8868 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
8869 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8870
8871 // The ongoing touch should not be canceled
8872 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
8873
8874 // Finger move is not ignored
8875 x += 10, y += 10;
8876 processPosition(mapper, x, y);
8877 processSync(mapper);
8878 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8879 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
8880
8881 // Reactivate display viewport
8882 displayViewport.isActive = true;
8883 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
8884 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8885
8886 // Finger move continues and does not start new gesture
8887 x += 10, y += 10;
8888 processPosition(mapper, x, y);
8889 processSync(mapper);
8890 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8891 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
8892}
8893
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008894TEST_F(MultiTouchInputMapperTest, VideoFrames_ReceivedByListener) {
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008895 prepareAxes(POSITION);
8896 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008897 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00008898 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008899
8900 NotifyMotionArgs motionArgs;
8901 // Unrotated video frame
8902 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8903 std::vector<TouchVideoFrame> frames{frame};
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008904 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008905 processPosition(mapper, 100, 200);
8906 processSync(mapper);
8907 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8908 ASSERT_EQ(frames, motionArgs.videoFrames);
8909
8910 // Subsequent touch events should not have any videoframes
8911 // This is implemented separately in FakeEventHub,
8912 // but that should match the behaviour of TouchVideoDevice.
8913 processPosition(mapper, 200, 200);
8914 processSync(mapper);
8915 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8916 ASSERT_EQ(std::vector<TouchVideoFrame>(), motionArgs.videoFrames);
8917}
8918
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008919TEST_F(MultiTouchInputMapperTest, VideoFrames_AreNotRotated) {
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008920 prepareAxes(POSITION);
8921 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00008922 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008923 // Unrotated video frame
8924 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8925 NotifyMotionArgs motionArgs;
8926
8927 // Test all 4 orientations
Michael Wrighta9cf4192022-12-01 23:46:39 +00008928 for (ui::Rotation orientation : ftl::enum_range<ui::Rotation>()) {
Harry Cuttsc57cd3c2024-04-24 13:52:55 +00008929 SCOPED_TRACE(StringPrintf("Orientation %s", ftl::enum_string(orientation).c_str()));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008930 clearViewports();
8931 prepareDisplay(orientation);
8932 std::vector<TouchVideoFrame> frames{frame};
8933 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
8934 processPosition(mapper, 100, 200);
8935 processSync(mapper);
8936 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8937 ASSERT_EQ(frames, motionArgs.videoFrames);
8938 }
8939}
8940
8941TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_AreRotated) {
8942 prepareAxes(POSITION);
8943 addConfigurationProperty("touch.deviceType", "touchScreen");
8944 // Since InputReader works in the un-rotated coordinate space, only devices that are not
8945 // orientation-aware are affected by display rotation.
8946 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00008947 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008948 // Unrotated video frame
8949 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8950 NotifyMotionArgs motionArgs;
8951
8952 // Test all 4 orientations
Michael Wrighta9cf4192022-12-01 23:46:39 +00008953 for (ui::Rotation orientation : ftl::enum_range<ui::Rotation>()) {
Harry Cuttsc57cd3c2024-04-24 13:52:55 +00008954 SCOPED_TRACE(StringPrintf("Orientation %s", ftl::enum_string(orientation).c_str()));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008955 clearViewports();
8956 prepareDisplay(orientation);
8957 std::vector<TouchVideoFrame> frames{frame};
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008958 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008959 processPosition(mapper, 100, 200);
8960 processSync(mapper);
8961 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008962 // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction
8963 // compared to the display. This is so that when the window transform (which contains the
8964 // display rotation) is applied later by InputDispatcher, the coordinates end up in the
8965 // window's coordinate space.
8966 frames[0].rotate(getInverseRotation(orientation));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008967 ASSERT_EQ(frames, motionArgs.videoFrames);
lilinnan687e58f2022-07-19 16:00:50 +08008968
8969 // Release finger.
8970 processSync(mapper);
8971 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008972 }
8973}
8974
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008975TEST_F(MultiTouchInputMapperTest, VideoFrames_MultipleFramesAreNotRotated) {
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008976 prepareAxes(POSITION);
8977 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00008978 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008979 // Unrotated video frames. There's no rule that they must all have the same dimensions,
8980 // so mix these.
8981 TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8982 TouchVideoFrame frame2(3, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {1, 3});
8983 TouchVideoFrame frame3(2, 2, {10, 20, 10, 0}, {1, 4});
8984 std::vector<TouchVideoFrame> frames{frame1, frame2, frame3};
8985 NotifyMotionArgs motionArgs;
8986
Michael Wrighta9cf4192022-12-01 23:46:39 +00008987 prepareDisplay(ui::ROTATION_90);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008988 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008989 processPosition(mapper, 100, 200);
8990 processSync(mapper);
8991 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008992 ASSERT_EQ(frames, motionArgs.videoFrames);
8993}
8994
8995TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_MultipleFramesAreRotated) {
8996 prepareAxes(POSITION);
8997 addConfigurationProperty("touch.deviceType", "touchScreen");
8998 // Since InputReader works in the un-rotated coordinate space, only devices that are not
8999 // orientation-aware are affected by display rotation.
9000 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00009001 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009002 // Unrotated video frames. There's no rule that they must all have the same dimensions,
9003 // so mix these.
9004 TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
9005 TouchVideoFrame frame2(3, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {1, 3});
9006 TouchVideoFrame frame3(2, 2, {10, 20, 10, 0}, {1, 4});
9007 std::vector<TouchVideoFrame> frames{frame1, frame2, frame3};
9008 NotifyMotionArgs motionArgs;
9009
Michael Wrighta9cf4192022-12-01 23:46:39 +00009010 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009011 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
9012 processPosition(mapper, 100, 200);
9013 processSync(mapper);
9014 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9015 std::for_each(frames.begin(), frames.end(), [](TouchVideoFrame& frame) {
9016 // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction
9017 // compared to the display. This is so that when the window transform (which contains the
9018 // display rotation) is applied later by InputDispatcher, the coordinates end up in the
9019 // window's coordinate space.
Michael Wrighta9cf4192022-12-01 23:46:39 +00009020 frame.rotate(getInverseRotation(ui::ROTATION_90));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009021 });
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009022 ASSERT_EQ(frames, motionArgs.videoFrames);
9023}
9024
Arthur Hung9da14732019-09-02 16:16:58 +08009025/**
9026 * If we had defined port associations, but the viewport is not ready, the touch device would be
9027 * expected to be disabled, and it should be enabled after the viewport has found.
9028 */
9029TEST_F(MultiTouchInputMapperTest, Configure_EnabledForAssociatedDisplay) {
Arthur Hung9da14732019-09-02 16:16:58 +08009030 constexpr uint8_t hdmi2 = 1;
9031 const std::string secondaryUniqueId = "uniqueId2";
Michael Wrightfe3de7d2020-07-02 19:05:30 +01009032 constexpr ViewportType type = ViewportType::EXTERNAL;
Arthur Hung9da14732019-09-02 16:16:58 +08009033
9034 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi2);
9035
9036 addConfigurationProperty("touch.deviceType", "touchScreen");
9037 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00009038 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung9da14732019-09-02 16:16:58 +08009039
9040 ASSERT_EQ(mDevice->isEnabled(), false);
9041
9042 // Add display on hdmi2, the device should be enabled and can receive touch event.
9043 prepareSecondaryDisplay(type, hdmi2);
9044 ASSERT_EQ(mDevice->isEnabled(), true);
9045
9046 // Send a touch event.
9047 processPosition(mapper, 100, 100);
9048 processSync(mapper);
9049
9050 NotifyMotionArgs args;
9051 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9052 ASSERT_EQ(SECONDARY_DISPLAY_ID, args.displayId);
9053}
9054
Arthur Hung421eb1c2020-01-16 00:09:42 +08009055TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleSingleTouch) {
Arthur Hung421eb1c2020-01-16 00:09:42 +08009056 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009057 prepareDisplay(ui::ROTATION_0);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009058 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009059 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung421eb1c2020-01-16 00:09:42 +08009060
9061 NotifyMotionArgs motionArgs;
9062
9063 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
9064 // finger down
9065 processId(mapper, 1);
9066 processPosition(mapper, x1, y1);
9067 processSync(mapper);
9068 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9069 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009070 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009071
9072 // finger move
9073 processId(mapper, 1);
9074 processPosition(mapper, x2, y2);
9075 processSync(mapper);
9076 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9077 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009078 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009079
9080 // finger up.
9081 processId(mapper, -1);
9082 processSync(mapper);
9083 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9084 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009085 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009086
9087 // new finger down
9088 processId(mapper, 1);
9089 processPosition(mapper, x3, y3);
9090 processSync(mapper);
9091 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9092 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009093 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009094}
9095
9096/**
arthurhungcc7f9802020-04-30 17:55:40 +08009097 * Test single touch should be canceled when received the MT_TOOL_PALM event, and the following
9098 * MOVE and UP events should be ignored.
Arthur Hung421eb1c2020-01-16 00:09:42 +08009099 */
arthurhungcc7f9802020-04-30 17:55:40 +08009100TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_SinglePointer) {
Arthur Hung421eb1c2020-01-16 00:09:42 +08009101 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009102 prepareDisplay(ui::ROTATION_0);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009103 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009104 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung421eb1c2020-01-16 00:09:42 +08009105
9106 NotifyMotionArgs motionArgs;
9107
9108 // default tool type is finger
9109 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
arthurhungcc7f9802020-04-30 17:55:40 +08009110 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009111 processPosition(mapper, x1, y1);
9112 processSync(mapper);
9113 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9114 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009115 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009116
9117 // Tool changed to MT_TOOL_PALM expect sending the cancel event.
9118 processToolType(mapper, MT_TOOL_PALM);
9119 processSync(mapper);
9120 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9121 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9122
9123 // Ignore the following MOVE and UP events if had detect a palm event.
arthurhungcc7f9802020-04-30 17:55:40 +08009124 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009125 processPosition(mapper, x2, y2);
9126 processSync(mapper);
9127 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9128
9129 // finger up.
arthurhungcc7f9802020-04-30 17:55:40 +08009130 processId(mapper, INVALID_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009131 processSync(mapper);
9132 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9133
9134 // new finger down
arthurhungcc7f9802020-04-30 17:55:40 +08009135 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009136 processToolType(mapper, MT_TOOL_FINGER);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009137 processPosition(mapper, x3, y3);
9138 processSync(mapper);
9139 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9140 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009141 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009142}
9143
arthurhungbf89a482020-04-17 17:37:55 +08009144/**
arthurhungcc7f9802020-04-30 17:55:40 +08009145 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event from some finger,
9146 * and the rest active fingers could still be allowed to receive the events
arthurhungbf89a482020-04-17 17:37:55 +08009147 */
arthurhungcc7f9802020-04-30 17:55:40 +08009148TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_TwoPointers) {
arthurhungbf89a482020-04-17 17:37:55 +08009149 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009150 prepareDisplay(ui::ROTATION_0);
arthurhungbf89a482020-04-17 17:37:55 +08009151 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009152 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungbf89a482020-04-17 17:37:55 +08009153
9154 NotifyMotionArgs motionArgs;
9155
9156 // default tool type is finger
arthurhungcc7f9802020-04-30 17:55:40 +08009157 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220;
9158 processId(mapper, FIRST_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009159 processPosition(mapper, x1, y1);
9160 processSync(mapper);
9161 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9162 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009163 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungbf89a482020-04-17 17:37:55 +08009164
9165 // Second finger down.
arthurhungcc7f9802020-04-30 17:55:40 +08009166 processSlot(mapper, SECOND_SLOT);
9167 processId(mapper, SECOND_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009168 processPosition(mapper, x2, y2);
arthurhungcc7f9802020-04-30 17:55:40 +08009169 processSync(mapper);
9170 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009171 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009172 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009173
9174 // If the tool type of the first finger changes to MT_TOOL_PALM,
9175 // we expect to receive ACTION_POINTER_UP with cancel flag.
9176 processSlot(mapper, FIRST_SLOT);
9177 processId(mapper, FIRST_TRACKING_ID);
9178 processToolType(mapper, MT_TOOL_PALM);
9179 processSync(mapper);
9180 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009181 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009182 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9183
9184 // The following MOVE events of second finger should be processed.
9185 processSlot(mapper, SECOND_SLOT);
9186 processId(mapper, SECOND_TRACKING_ID);
9187 processPosition(mapper, x2 + 1, y2 + 1);
9188 processSync(mapper);
9189 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9190 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009191 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009192
9193 // First finger up. It used to be in palm mode, and we already generated ACTION_POINTER_UP for
9194 // it. Second finger receive move.
9195 processSlot(mapper, FIRST_SLOT);
9196 processId(mapper, INVALID_TRACKING_ID);
9197 processSync(mapper);
9198 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9199 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009200 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009201
9202 // Second finger keeps moving.
9203 processSlot(mapper, SECOND_SLOT);
9204 processId(mapper, SECOND_TRACKING_ID);
9205 processPosition(mapper, x2 + 2, y2 + 2);
9206 processSync(mapper);
9207 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9208 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009209 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009210
9211 // Second finger up.
9212 processId(mapper, INVALID_TRACKING_ID);
9213 processSync(mapper);
9214 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9215 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9216 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9217}
9218
9219/**
9220 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event, if only 1 finger
9221 * is active, it should send CANCEL after receiving the MT_TOOL_PALM event.
9222 */
9223TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_ShouldCancelWhenAllTouchIsPalm) {
9224 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009225 prepareDisplay(ui::ROTATION_0);
arthurhungcc7f9802020-04-30 17:55:40 +08009226 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009227 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungcc7f9802020-04-30 17:55:40 +08009228
9229 NotifyMotionArgs motionArgs;
9230
9231 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
9232 // First finger down.
9233 processId(mapper, FIRST_TRACKING_ID);
9234 processPosition(mapper, x1, y1);
9235 processSync(mapper);
9236 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9237 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009238 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009239
9240 // Second finger down.
9241 processSlot(mapper, SECOND_SLOT);
9242 processId(mapper, SECOND_TRACKING_ID);
9243 processPosition(mapper, x2, y2);
arthurhungbf89a482020-04-17 17:37:55 +08009244 processSync(mapper);
9245 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009246 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009247 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungbf89a482020-04-17 17:37:55 +08009248
arthurhungcc7f9802020-04-30 17:55:40 +08009249 // If the tool type of the first finger changes to MT_TOOL_PALM,
9250 // we expect to receive ACTION_POINTER_UP with cancel flag.
9251 processSlot(mapper, FIRST_SLOT);
9252 processId(mapper, FIRST_TRACKING_ID);
9253 processToolType(mapper, MT_TOOL_PALM);
9254 processSync(mapper);
9255 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009256 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009257 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9258
9259 // Second finger keeps moving.
9260 processSlot(mapper, SECOND_SLOT);
9261 processId(mapper, SECOND_TRACKING_ID);
9262 processPosition(mapper, x2 + 1, y2 + 1);
9263 processSync(mapper);
9264 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9265 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9266
9267 // second finger becomes palm, receive cancel due to only 1 finger is active.
9268 processId(mapper, SECOND_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009269 processToolType(mapper, MT_TOOL_PALM);
9270 processSync(mapper);
9271 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9272 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9273
arthurhungcc7f9802020-04-30 17:55:40 +08009274 // third finger down.
9275 processSlot(mapper, THIRD_SLOT);
9276 processId(mapper, THIRD_TRACKING_ID);
9277 processToolType(mapper, MT_TOOL_FINGER);
arthurhungbf89a482020-04-17 17:37:55 +08009278 processPosition(mapper, x3, y3);
9279 processSync(mapper);
arthurhungbf89a482020-04-17 17:37:55 +08009280 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);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009283 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009284
9285 // third finger move
9286 processId(mapper, THIRD_TRACKING_ID);
9287 processPosition(mapper, x3 + 1, y3 + 1);
9288 processSync(mapper);
9289 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9290 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9291
9292 // first finger up, third finger receive move.
9293 processSlot(mapper, FIRST_SLOT);
9294 processId(mapper, INVALID_TRACKING_ID);
9295 processSync(mapper);
9296 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9297 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009298 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009299
9300 // second finger up, third finger receive move.
9301 processSlot(mapper, SECOND_SLOT);
9302 processId(mapper, INVALID_TRACKING_ID);
9303 processSync(mapper);
9304 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9305 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009306 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009307
9308 // third finger up.
9309 processSlot(mapper, THIRD_SLOT);
9310 processId(mapper, INVALID_TRACKING_ID);
9311 processSync(mapper);
9312 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9313 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9314 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9315}
9316
9317/**
9318 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event from some finger,
9319 * and the active finger could still be allowed to receive the events
9320 */
9321TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_KeepFirstPointer) {
9322 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009323 prepareDisplay(ui::ROTATION_0);
arthurhungcc7f9802020-04-30 17:55:40 +08009324 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009325 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungcc7f9802020-04-30 17:55:40 +08009326
9327 NotifyMotionArgs motionArgs;
9328
9329 // default tool type is finger
9330 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220;
9331 processId(mapper, FIRST_TRACKING_ID);
9332 processPosition(mapper, x1, y1);
9333 processSync(mapper);
9334 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9335 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009336 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009337
9338 // Second finger down.
9339 processSlot(mapper, SECOND_SLOT);
9340 processId(mapper, SECOND_TRACKING_ID);
9341 processPosition(mapper, x2, y2);
9342 processSync(mapper);
9343 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009344 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009345 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009346
9347 // If the tool type of the second finger changes to MT_TOOL_PALM,
9348 // we expect to receive ACTION_POINTER_UP with cancel flag.
9349 processId(mapper, SECOND_TRACKING_ID);
9350 processToolType(mapper, MT_TOOL_PALM);
9351 processSync(mapper);
9352 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009353 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009354 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9355
9356 // The following MOVE event should be processed.
9357 processSlot(mapper, FIRST_SLOT);
9358 processId(mapper, FIRST_TRACKING_ID);
9359 processPosition(mapper, x1 + 1, y1 + 1);
9360 processSync(mapper);
9361 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9362 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009363 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009364
9365 // second finger up.
9366 processSlot(mapper, SECOND_SLOT);
9367 processId(mapper, INVALID_TRACKING_ID);
9368 processSync(mapper);
9369 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9370 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9371
9372 // first finger keep moving
9373 processSlot(mapper, FIRST_SLOT);
9374 processId(mapper, FIRST_TRACKING_ID);
9375 processPosition(mapper, x1 + 2, y1 + 2);
9376 processSync(mapper);
9377 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9378 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9379
9380 // first finger up.
9381 processId(mapper, INVALID_TRACKING_ID);
9382 processSync(mapper);
9383 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9384 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9385 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
arthurhungbf89a482020-04-17 17:37:55 +08009386}
9387
Arthur Hung9ad18942021-06-19 02:04:46 +00009388/**
9389 * Test multi-touch should sent ACTION_POINTER_UP/ACTION_UP when received the INVALID_TRACKING_ID,
9390 * to prevent the driver side may send unexpected data after set tracking id as INVALID_TRACKING_ID
9391 * cause slot be valid again.
9392 */
9393TEST_F(MultiTouchInputMapperTest, Process_MultiTouch_WithInvalidTrackingId) {
9394 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009395 prepareDisplay(ui::ROTATION_0);
Arthur Hung9ad18942021-06-19 02:04:46 +00009396 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009397 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung9ad18942021-06-19 02:04:46 +00009398
9399 NotifyMotionArgs motionArgs;
9400
9401 constexpr int32_t x1 = 100, y1 = 200, x2 = 0, y2 = 0;
9402 // First finger down.
9403 processId(mapper, FIRST_TRACKING_ID);
9404 processPosition(mapper, x1, y1);
9405 processPressure(mapper, RAW_PRESSURE_MAX);
9406 processSync(mapper);
9407 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9408 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009409 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009410
9411 // First finger move.
9412 processId(mapper, FIRST_TRACKING_ID);
9413 processPosition(mapper, x1 + 1, y1 + 1);
9414 processPressure(mapper, RAW_PRESSURE_MAX);
9415 processSync(mapper);
9416 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9417 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009418 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009419
9420 // Second finger down.
9421 processSlot(mapper, SECOND_SLOT);
9422 processId(mapper, SECOND_TRACKING_ID);
9423 processPosition(mapper, x2, y2);
9424 processPressure(mapper, RAW_PRESSURE_MAX);
9425 processSync(mapper);
9426 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009427 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009428 ASSERT_EQ(uint32_t(2), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009429
9430 // second finger up with some unexpected data.
9431 processSlot(mapper, SECOND_SLOT);
9432 processId(mapper, INVALID_TRACKING_ID);
9433 processPosition(mapper, x2, y2);
9434 processSync(mapper);
9435 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009436 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009437 ASSERT_EQ(uint32_t(2), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009438
9439 // first finger up with some unexpected data.
9440 processSlot(mapper, FIRST_SLOT);
9441 processId(mapper, INVALID_TRACKING_ID);
9442 processPosition(mapper, x2, y2);
9443 processPressure(mapper, RAW_PRESSURE_MAX);
9444 processSync(mapper);
9445 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9446 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009447 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009448}
9449
Arpit Singh4b4a4572023-11-24 18:19:56 +00009450TEST_F(MultiTouchInputMapperTest, Reset_RepopulatesMultiTouchState) {
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009451 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009452 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009453 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009454 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009455
9456 // First finger down.
Arpit Singh4b4a4572023-11-24 18:19:56 +00009457 constexpr int32_t x1 = 100, y1 = 200, x2 = 300, y2 = 400;
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009458 processId(mapper, FIRST_TRACKING_ID);
Arpit Singh4b4a4572023-11-24 18:19:56 +00009459 processPosition(mapper, x1, y1);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009460 processPressure(mapper, RAW_PRESSURE_MAX);
9461 processSync(mapper);
9462 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9463 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
9464
9465 // Second finger down.
9466 processSlot(mapper, SECOND_SLOT);
9467 processId(mapper, SECOND_TRACKING_ID);
Arpit Singh4b4a4572023-11-24 18:19:56 +00009468 processPosition(mapper, x2, y2);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009469 processPressure(mapper, RAW_PRESSURE_MAX);
9470 processSync(mapper);
9471 ASSERT_NO_FATAL_FAILURE(
9472 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(ACTION_POINTER_1_DOWN)));
9473
Arpit Singh4b4a4572023-11-24 18:19:56 +00009474 // Set MT Slot state to be repopulated for the required slots
9475 std::vector<int32_t> mtSlotValues(RAW_SLOT_MAX + 1, -1);
9476 mtSlotValues[0] = FIRST_TRACKING_ID;
9477 mtSlotValues[1] = SECOND_TRACKING_ID;
9478 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_TRACKING_ID, mtSlotValues);
9479
9480 mtSlotValues[0] = x1;
9481 mtSlotValues[1] = x2;
9482 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_POSITION_X, mtSlotValues);
9483
9484 mtSlotValues[0] = y1;
9485 mtSlotValues[1] = y2;
9486 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_POSITION_Y, mtSlotValues);
9487
9488 mtSlotValues[0] = RAW_PRESSURE_MAX;
9489 mtSlotValues[1] = RAW_PRESSURE_MAX;
9490 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_PRESSURE, mtSlotValues);
9491
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009492 // Reset the mapper. When the mapper is reset, we expect the current multi-touch state to be
Arpit Singh4b4a4572023-11-24 18:19:56 +00009493 // repopulated. Resetting should cancel the ongoing gesture.
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00009494 resetMapper(mapper, ARBITRARY_TIME);
9495 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9496 WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009497
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009498 // Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
9499 // the existing touch state to generate a down event.
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009500 processPosition(mapper, 301, 302);
9501 processSync(mapper);
9502 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9503 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPressure(1.f))));
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009504 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9505 AllOf(WithMotionAction(ACTION_POINTER_1_DOWN), WithPressure(1.f))));
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009506
9507 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9508}
9509
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009510TEST_F(MultiTouchInputMapperTest, Reset_PreservesLastTouchState_NoPointersDown) {
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009511 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009512 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009513 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009514 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009515
9516 // First finger touches down and releases.
9517 processId(mapper, FIRST_TRACKING_ID);
9518 processPosition(mapper, 100, 200);
9519 processPressure(mapper, RAW_PRESSURE_MAX);
9520 processSync(mapper);
9521 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9522 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
9523 processId(mapper, INVALID_TRACKING_ID);
9524 processSync(mapper);
9525 ASSERT_NO_FATAL_FAILURE(
9526 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
9527
9528 // Reset the mapper. When the mapper is reset, we expect it to restore the latest
9529 // raw state where no pointers are down.
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00009530 resetMapper(mapper, ARBITRARY_TIME);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009531 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9532
9533 // Send an empty sync frame. Since there are no pointers, no events are generated.
9534 processSync(mapper);
9535 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9536}
9537
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009538TEST_F(MultiTouchInputMapperTest, StylusSourceIsAddedDynamicallyFromToolType) {
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009539 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009540 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009541 prepareAxes(POSITION | ID | SLOT | PRESSURE | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009542 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009543 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009544
9545 // Even if the device supports reporting the ABS_MT_TOOL_TYPE axis, which could give it the
9546 // ability to report MT_TOOL_PEN, we do not report the device as coming from a stylus source.
9547 // Due to limitations in the evdev protocol, we cannot say for certain that a device is capable
9548 // of reporting stylus events just because it supports ABS_MT_TOOL_TYPE.
9549 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
9550
9551 // However, if the device ever ends up reporting an event with MT_TOOL_PEN, it should be
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009552 // reported with the stylus source.
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009553 processId(mapper, FIRST_TRACKING_ID);
9554 processToolType(mapper, MT_TOOL_PEN);
9555 processPosition(mapper, 100, 200);
9556 processPressure(mapper, RAW_PRESSURE_MAX);
9557 processSync(mapper);
9558 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9559 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
9560 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009561 WithToolType(ToolType::STYLUS))));
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009562
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009563 // Now that we know the device supports styluses, ensure that the device is re-configured with
9564 // the stylus source.
9565 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, mapper.getSources());
9566 {
9567 const auto& devices = mReader->getInputDevices();
9568 auto deviceInfo =
9569 std::find_if(devices.begin(), devices.end(),
9570 [](const InputDeviceInfo& info) { return info.getId() == DEVICE_ID; });
9571 LOG_ALWAYS_FATAL_IF(deviceInfo == devices.end(), "Cannot find InputDevice");
9572 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, deviceInfo->getSources());
9573 }
9574
9575 // Ensure the device was not reset to prevent interruptions of any ongoing gestures.
9576 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
9577
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009578 processId(mapper, INVALID_TRACKING_ID);
9579 processSync(mapper);
9580 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9581 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
9582 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009583 WithToolType(ToolType::STYLUS))));
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009584}
9585
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009586// --- MultiTouchInputMapperTest_ExternalDevice ---
9587
9588class MultiTouchInputMapperTest_ExternalDevice : public MultiTouchInputMapperTest {
9589protected:
Chris Yea52ade12020-08-27 16:49:20 -07009590 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL); }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009591};
9592
9593/**
9594 * Expect fallback to internal viewport if device is external and external viewport is not present.
9595 */
9596TEST_F(MultiTouchInputMapperTest_ExternalDevice, Viewports_Fallback) {
9597 prepareAxes(POSITION);
9598 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009599 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00009600 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009601
9602 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
9603
9604 NotifyMotionArgs motionArgs;
9605
9606 // Expect the event to be sent to the internal viewport,
9607 // because an external viewport is not present.
9608 processPosition(mapper, 100, 100);
9609 processSync(mapper);
9610 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009611 ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, motionArgs.displayId);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009612
9613 // Expect the event to be sent to the external viewport if it is present.
Michael Wrightfe3de7d2020-07-02 19:05:30 +01009614 prepareSecondaryDisplay(ViewportType::EXTERNAL);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009615 processPosition(mapper, 100, 100);
9616 processSync(mapper);
9617 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9618 ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
9619}
Arthur Hung4197f6b2020-03-16 15:39:59 +08009620
Prabir Pradhan3ed7e352024-05-03 23:59:43 +00009621// TODO(b/281840344): Remove the test when the old touchpad stack is removed. It is currently
9622// unclear what the behavior of the touchpad logic in TouchInputMapper should do after the
9623// PointerChoreographer refactor.
9624TEST_F(MultiTouchInputMapperTest, DISABLED_Process_TouchpadPointer) {
Harry Cutts8722be92024-04-05 14:46:05 +00009625 // prepare device
Michael Wrighta9cf4192022-12-01 23:46:39 +00009626 prepareDisplay(ui::ROTATION_0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009627 prepareAxes(POSITION | ID | SLOT);
9628 mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
9629 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00009630 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009631 // run uncaptured pointer tests - pushes out generic events
9632 // FINGER 0 DOWN
9633 processId(mapper, 3);
9634 processPosition(mapper, 100, 100);
9635 processKey(mapper, BTN_TOUCH, 1);
9636 processSync(mapper);
9637
9638 // start at (100,100), cursor should be at (0,0) * scale
9639 NotifyMotionArgs args;
9640 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9641 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
9642 ASSERT_NO_FATAL_FAILURE(
9643 assertPointerCoords(args.pointerCoords[0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
9644
9645 // FINGER 0 MOVE
9646 processPosition(mapper, 200, 200);
9647 processSync(mapper);
9648
9649 // compute scaling to help with touch position checking
9650 float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
9651 float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
9652 float scale =
9653 mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
9654
9655 // translate from (100,100) -> (200,200), cursor should have changed to (100,100) * scale)
9656 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9657 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
9658 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], 100 * scale, 100 * scale, 0,
9659 0, 0, 0, 0, 0, 0, 0));
LiZhihong758eb562022-11-03 15:28:29 +08009660
9661 // BUTTON DOWN
9662 processKey(mapper, BTN_LEFT, 1);
9663 processSync(mapper);
9664
9665 // touchinputmapper design sends a move before button press
9666 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9667 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
9668 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9669 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, args.action);
9670
9671 // BUTTON UP
9672 processKey(mapper, BTN_LEFT, 0);
9673 processSync(mapper);
9674
9675 // touchinputmapper design sends a move after button release
9676 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9677 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, args.action);
9678 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9679 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009680}
9681
Harry Cutts8722be92024-04-05 14:46:05 +00009682TEST_F(MultiTouchInputMapperTest, Touchpad_GetSources) {
Michael Wrighta9cf4192022-12-01 23:46:39 +00009683 prepareDisplay(ui::ROTATION_0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009684 prepareAxes(POSITION | ID | SLOT);
9685 mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
Hiroki Sato25040232024-02-22 17:21:22 +09009686 mFakePolicy->setPointerCapture(/*window=*/nullptr);
Arpit Singha8c236b2023-04-25 13:56:05 +00009687 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009688
Josep del Río2d8c79a2023-01-23 19:33:50 +00009689 // uncaptured touchpad should be a pointer device
9690 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009691}
9692
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009693// --- BluetoothMultiTouchInputMapperTest ---
9694
9695class BluetoothMultiTouchInputMapperTest : public MultiTouchInputMapperTest {
9696protected:
9697 void SetUp() override {
9698 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL, BUS_BLUETOOTH);
9699 }
9700};
9701
9702TEST_F(BluetoothMultiTouchInputMapperTest, TimestampSmoothening) {
9703 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009704 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009705 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009706 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009707
9708 nsecs_t kernelEventTime = ARBITRARY_TIME;
9709 nsecs_t expectedEventTime = ARBITRARY_TIME;
9710 // Touch down.
9711 processId(mapper, FIRST_TRACKING_ID);
9712 processPosition(mapper, 100, 200);
9713 processPressure(mapper, RAW_PRESSURE_MAX);
9714 processSync(mapper, ARBITRARY_TIME);
9715 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9716 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithEventTime(ARBITRARY_TIME))));
9717
9718 // Process several events that come in quick succession, according to their timestamps.
9719 for (int i = 0; i < 3; i++) {
9720 constexpr static nsecs_t delta = ms2ns(1);
9721 static_assert(delta < MIN_BLUETOOTH_TIMESTAMP_DELTA);
9722 kernelEventTime += delta;
9723 expectedEventTime += MIN_BLUETOOTH_TIMESTAMP_DELTA;
9724
9725 processPosition(mapper, 101 + i, 201 + i);
9726 processSync(mapper, kernelEventTime);
9727 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9728 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
9729 WithEventTime(expectedEventTime))));
9730 }
9731
9732 // Release the touch.
9733 processId(mapper, INVALID_TRACKING_ID);
9734 processPressure(mapper, RAW_PRESSURE_MIN);
9735 processSync(mapper, ARBITRARY_TIME + ms2ns(50));
9736 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9737 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
9738 WithEventTime(ARBITRARY_TIME + ms2ns(50)))));
9739}
9740
9741// --- MultiTouchPointerModeTest ---
9742
HQ Liue6983c72022-04-19 22:14:56 +00009743class MultiTouchPointerModeTest : public MultiTouchInputMapperTest {
9744protected:
9745 float mPointerMovementScale;
9746 float mPointerXZoomScale;
9747 void preparePointerMode(int xAxisResolution, int yAxisResolution) {
9748 addConfigurationProperty("touch.deviceType", "pointer");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009749 prepareDisplay(ui::ROTATION_0);
HQ Liue6983c72022-04-19 22:14:56 +00009750
9751 prepareAxes(POSITION);
9752 prepareAbsoluteAxisResolution(xAxisResolution, yAxisResolution);
9753 // In order to enable swipe and freeform gesture in pointer mode, pointer capture
9754 // needs to be disabled, and the pointer gesture needs to be enabled.
Hiroki Sato25040232024-02-22 17:21:22 +09009755 mFakePolicy->setPointerCapture(/*window=*/nullptr);
HQ Liue6983c72022-04-19 22:14:56 +00009756 mFakePolicy->setPointerGestureEnabled(true);
HQ Liue6983c72022-04-19 22:14:56 +00009757
9758 float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
9759 float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
9760 mPointerMovementScale =
9761 mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
9762 mPointerXZoomScale =
9763 mFakePolicy->getPointerGestureZoomSpeedRatio() * displayDiagonal / rawDiagonal;
9764 }
9765
9766 void prepareAbsoluteAxisResolution(int xAxisResolution, int yAxisResolution) {
9767 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX,
9768 /*flat*/ 0,
9769 /*fuzz*/ 0, /*resolution*/ xAxisResolution);
9770 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX,
9771 /*flat*/ 0,
9772 /*fuzz*/ 0, /*resolution*/ yAxisResolution);
9773 }
9774};
9775
9776/**
9777 * Two fingers down on a pointer mode touch pad. The width
9778 * of the two finger is larger than 1/4 of the touch pack diagnal length. However, it
9779 * is smaller than the fixed min physical length 30mm. Two fingers' distance must
9780 * be greater than the both value to be freeform gesture, so that after two
9781 * fingers start to move downwards, the gesture should be swipe.
9782 */
9783TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthSwipe) {
9784 // The min freeform gesture width is 25units/mm x 30mm = 750
9785 // which is greater than fraction of the diagnal length of the touchpad (349).
9786 // Thus, MaxSwipWidth is 750.
Harry Cutts33476232023-01-30 19:57:29 +00009787 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +00009788 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009789 NotifyMotionArgs motionArgs;
9790
9791 // Two fingers down at once.
9792 // The two fingers are 450 units apart, expects the current gesture to be PRESS
9793 // Pointer's initial position is used the [0,0] coordinate.
9794 int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125;
9795
9796 processId(mapper, FIRST_TRACKING_ID);
9797 processPosition(mapper, x1, y1);
9798 processMTSync(mapper);
9799 processId(mapper, SECOND_TRACKING_ID);
9800 processPosition(mapper, x2, y2);
9801 processMTSync(mapper);
9802 processSync(mapper);
9803
9804 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009805 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009806 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009807 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009808 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009809 ASSERT_NO_FATAL_FAILURE(
9810 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9811
9812 // It should be recognized as a SWIPE gesture when two fingers start to move down,
9813 // that there should be 1 pointer.
9814 int32_t movingDistance = 200;
9815 y1 += movingDistance;
9816 y2 += movingDistance;
9817
9818 processId(mapper, FIRST_TRACKING_ID);
9819 processPosition(mapper, x1, y1);
9820 processMTSync(mapper);
9821 processId(mapper, SECOND_TRACKING_ID);
9822 processPosition(mapper, x2, y2);
9823 processMTSync(mapper);
9824 processSync(mapper);
9825
9826 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009827 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009828 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009829 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009830 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009831 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
9832 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9833 0, 0, 0, 0));
9834}
9835
9836/**
9837 * Two fingers down on a pointer mode touch pad. The width of the two finger is larger
9838 * than the minimum freeform gesture width, 30mm. However, it is smaller than 1/4 of
9839 * the touch pack diagnal length. Two fingers' distance must be greater than the both
9840 * value to be freeform gesture, so that after two fingers start to move downwards,
9841 * the gesture should be swipe.
9842 */
9843TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthLowResolutionSwipe) {
9844 // The min freeform gesture width is 5units/mm x 30mm = 150
9845 // which is greater than fraction of the diagnal length of the touchpad (349).
9846 // Thus, MaxSwipWidth is the fraction of the diagnal length, 349.
Harry Cutts33476232023-01-30 19:57:29 +00009847 preparePointerMode(/*xResolution=*/5, /*yResolution=*/5);
Arpit Singha8c236b2023-04-25 13:56:05 +00009848 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009849 NotifyMotionArgs motionArgs;
9850
9851 // Two fingers down at once.
9852 // The two fingers are 250 units apart, expects the current gesture to be PRESS
9853 // Pointer's initial position is used the [0,0] coordinate.
9854 int32_t x1 = 100, y1 = 125, x2 = 350, y2 = 125;
9855
9856 processId(mapper, FIRST_TRACKING_ID);
9857 processPosition(mapper, x1, y1);
9858 processMTSync(mapper);
9859 processId(mapper, SECOND_TRACKING_ID);
9860 processPosition(mapper, x2, y2);
9861 processMTSync(mapper);
9862 processSync(mapper);
9863
9864 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009865 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009866 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009867 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009868 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009869 ASSERT_NO_FATAL_FAILURE(
9870 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9871
9872 // It should be recognized as a SWIPE gesture when two fingers start to move down,
9873 // and there should be 1 pointer.
9874 int32_t movingDistance = 200;
9875 y1 += movingDistance;
9876 y2 += movingDistance;
9877
9878 processId(mapper, FIRST_TRACKING_ID);
9879 processPosition(mapper, x1, y1);
9880 processMTSync(mapper);
9881 processId(mapper, SECOND_TRACKING_ID);
9882 processPosition(mapper, x2, y2);
9883 processMTSync(mapper);
9884 processSync(mapper);
9885
9886 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009887 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009888 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009889 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009890 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009891 // New coordinate is the scaled relative coordinate from the initial coordinate.
9892 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
9893 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9894 0, 0, 0, 0));
9895}
9896
9897/**
9898 * Touch the touch pad with two fingers with a distance wider than the minimum freeform
9899 * gesture width and 1/4 of the diagnal length of the touchpad. Expect to receive
9900 * freeform gestures after two fingers start to move downwards.
9901 */
9902TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthFreeform) {
Harry Cutts33476232023-01-30 19:57:29 +00009903 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +00009904 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009905
9906 NotifyMotionArgs motionArgs;
9907
9908 // Two fingers down at once. Wider than the max swipe width.
9909 // The gesture is expected to be PRESS, then transformed to FREEFORM
9910 int32_t x1 = 100, y1 = 125, x2 = 900, y2 = 125;
9911
9912 processId(mapper, FIRST_TRACKING_ID);
9913 processPosition(mapper, x1, y1);
9914 processMTSync(mapper);
9915 processId(mapper, SECOND_TRACKING_ID);
9916 processPosition(mapper, x2, y2);
9917 processMTSync(mapper);
9918 processSync(mapper);
9919
9920 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009921 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009922 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009923 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009924 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009925 // One pointer for PRESS, and its coordinate is used as the origin for pointer coordinates.
9926 ASSERT_NO_FATAL_FAILURE(
9927 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9928
9929 int32_t movingDistance = 200;
9930
9931 // Move two fingers down, expect a cancel event because gesture is changing to freeform,
9932 // then two down events for two pointers.
9933 y1 += movingDistance;
9934 y2 += movingDistance;
9935
9936 processId(mapper, FIRST_TRACKING_ID);
9937 processPosition(mapper, x1, y1);
9938 processMTSync(mapper);
9939 processId(mapper, SECOND_TRACKING_ID);
9940 processPosition(mapper, x2, y2);
9941 processMTSync(mapper);
9942 processSync(mapper);
9943
9944 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9945 // The previous PRESS gesture is cancelled, because it is transformed to freeform
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009946 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009947 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9948 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009949 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009950 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009951 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
9952 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009953 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009954 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009955 ASSERT_EQ(2U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009956 ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN, motionArgs.action & AMOTION_EVENT_ACTION_MASK);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009957 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009958 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009959 // Two pointers' scaled relative coordinates from their initial centroid.
9960 // Initial y coordinates are 0 as y1 and y2 have the same value.
9961 float cookedX1 = (x1 - x2) / 2 * mPointerXZoomScale;
9962 float cookedX2 = (x2 - x1) / 2 * mPointerXZoomScale;
9963 // When pointers move, the new coordinates equal to the initial coordinates plus
9964 // scaled moving distance.
9965 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
9966 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9967 0, 0, 0, 0));
9968 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], cookedX2,
9969 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9970 0, 0, 0, 0));
9971
9972 // Move two fingers down again, expect one MOVE motion event.
9973 y1 += movingDistance;
9974 y2 += movingDistance;
9975
9976 processId(mapper, FIRST_TRACKING_ID);
9977 processPosition(mapper, x1, y1);
9978 processMTSync(mapper);
9979 processId(mapper, SECOND_TRACKING_ID);
9980 processPosition(mapper, x2, y2);
9981 processMTSync(mapper);
9982 processSync(mapper);
9983
9984 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009985 ASSERT_EQ(2U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009986 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009987 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009988 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009989 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
9990 movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
9991 0, 0, 0, 0, 0));
9992 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], cookedX2,
9993 movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
9994 0, 0, 0, 0, 0));
9995}
9996
Harry Cutts39b7ca22022-10-05 15:55:48 +00009997TEST_F(MultiTouchPointerModeTest, TwoFingerSwipeOffsets) {
Harry Cutts33476232023-01-30 19:57:29 +00009998 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +00009999 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Harry Cutts39b7ca22022-10-05 15:55:48 +000010000 NotifyMotionArgs motionArgs;
10001
10002 // Place two fingers down.
10003 int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125;
10004
10005 processId(mapper, FIRST_TRACKING_ID);
10006 processPosition(mapper, x1, y1);
10007 processMTSync(mapper);
10008 processId(mapper, SECOND_TRACKING_ID);
10009 processPosition(mapper, x2, y2);
10010 processMTSync(mapper);
10011 processSync(mapper);
10012
10013 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010014 ASSERT_EQ(1U, motionArgs.getPointerCount());
Harry Cutts39b7ca22022-10-05 15:55:48 +000010015 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
10016 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
10017 ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET));
10018 ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET));
10019
10020 // Move the two fingers down and to the left.
10021 int32_t movingDistance = 200;
10022 x1 -= movingDistance;
10023 y1 += movingDistance;
10024 x2 -= movingDistance;
10025 y2 += movingDistance;
10026
10027 processId(mapper, FIRST_TRACKING_ID);
10028 processPosition(mapper, x1, y1);
10029 processMTSync(mapper);
10030 processId(mapper, SECOND_TRACKING_ID);
10031 processPosition(mapper, x2, y2);
10032 processMTSync(mapper);
10033 processSync(mapper);
10034
10035 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010036 ASSERT_EQ(1U, motionArgs.getPointerCount());
Harry Cutts39b7ca22022-10-05 15:55:48 +000010037 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
10038 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
10039 ASSERT_LT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET), 0);
10040 ASSERT_GT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET), 0);
10041}
10042
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010043TEST_F(MultiTouchPointerModeTest, WhenViewportActiveStatusChanged_PointerGestureIsReset) {
Harry Cutts33476232023-01-30 19:57:29 +000010044 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010045 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +000010046 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010047 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
10048
10049 // Start a stylus gesture.
10050 processKey(mapper, BTN_TOOL_PEN, 1);
10051 processId(mapper, FIRST_TRACKING_ID);
10052 processPosition(mapper, 100, 200);
10053 processSync(mapper);
10054 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10055 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
10056 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010057 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010058 // TODO(b/257078296): Pointer mode generates extra event.
10059 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10060 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
10061 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010062 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010063 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
10064
10065 // Make the viewport inactive. This will put the device in disabled mode, and the ongoing stylus
10066 // gesture should be disabled.
10067 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
10068 viewport->isActive = false;
10069 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +000010070 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010071 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10072 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
10073 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010074 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010075 // TODO(b/257078296): Pointer mode generates extra event.
10076 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10077 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
10078 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010079 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010080 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
10081}
10082
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010083// --- PeripheralControllerTest ---
Chris Yee2b1e5c2021-03-10 22:45:12 -080010084
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010085class PeripheralControllerTest : public testing::Test {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010086protected:
10087 static const char* DEVICE_NAME;
10088 static const char* DEVICE_LOCATION;
10089 static const int32_t DEVICE_ID;
10090 static const int32_t DEVICE_GENERATION;
10091 static const int32_t DEVICE_CONTROLLER_NUMBER;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010092 static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010093 static const int32_t EVENTHUB_ID;
10094
10095 std::shared_ptr<FakeEventHub> mFakeEventHub;
10096 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010097 std::unique_ptr<TestInputListener> mFakeListener;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010098 std::unique_ptr<InstrumentedInputReader> mReader;
10099 std::shared_ptr<InputDevice> mDevice;
10100
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010101 virtual void SetUp(ftl::Flags<InputDeviceClass> classes) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010102 mFakeEventHub = std::make_unique<FakeEventHub>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010103 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010104 mFakeListener = std::make_unique<TestInputListener>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010105 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010106 *mFakeListener);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010107 mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes);
10108 }
10109
10110 void SetUp() override { SetUp(DEVICE_CLASSES); }
10111
10112 void TearDown() override {
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010113 mFakeListener.reset();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010114 mFakePolicy.clear();
10115 }
10116
Chris Yee2b1e5c2021-03-10 22:45:12 -080010117 std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
10118 const std::string& location, int32_t eventHubId,
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010119 ftl::Flags<InputDeviceClass> classes) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010120 InputDeviceIdentifier identifier;
10121 identifier.name = name;
10122 identifier.location = location;
10123 std::shared_ptr<InputDevice> device =
10124 std::make_shared<InputDevice>(mReader->getContext(), deviceId, DEVICE_GENERATION,
10125 identifier);
10126 mReader->pushNextDevice(device);
10127 mFakeEventHub->addDevice(eventHubId, name, classes);
10128 mReader->loopOnce();
10129 return device;
10130 }
10131
10132 template <class T, typename... Args>
10133 T& addControllerAndConfigure(Args... args) {
10134 T& controller = mDevice->addController<T>(EVENTHUB_ID, args...);
10135
10136 return controller;
10137 }
10138};
10139
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010140const char* PeripheralControllerTest::DEVICE_NAME = "device";
10141const char* PeripheralControllerTest::DEVICE_LOCATION = "BLUETOOTH";
10142const int32_t PeripheralControllerTest::DEVICE_ID = END_RESERVED_ID + 1000;
10143const int32_t PeripheralControllerTest::DEVICE_GENERATION = 2;
10144const int32_t PeripheralControllerTest::DEVICE_CONTROLLER_NUMBER = 0;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010145const ftl::Flags<InputDeviceClass> PeripheralControllerTest::DEVICE_CLASSES =
10146 ftl::Flags<InputDeviceClass>(0); // not needed for current tests
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010147const int32_t PeripheralControllerTest::EVENTHUB_ID = 1;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010148
10149// --- BatteryControllerTest ---
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010150class BatteryControllerTest : public PeripheralControllerTest {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010151protected:
10152 void SetUp() override {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010153 PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::BATTERY);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010154 }
10155};
10156
10157TEST_F(BatteryControllerTest, GetBatteryCapacity) {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010158 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010159
Harry Cuttsa5b71292022-11-28 12:56:17 +000010160 ASSERT_TRUE(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY));
10161 ASSERT_EQ(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY).value_or(-1),
10162 FakeEventHub::BATTERY_CAPACITY);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010163}
10164
10165TEST_F(BatteryControllerTest, GetBatteryStatus) {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010166 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010167
Harry Cuttsa5b71292022-11-28 12:56:17 +000010168 ASSERT_TRUE(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY));
10169 ASSERT_EQ(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY).value_or(-1),
10170 FakeEventHub::BATTERY_STATUS);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010171}
10172
10173// --- LightControllerTest ---
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010174class LightControllerTest : public PeripheralControllerTest {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010175protected:
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010176 void SetUp() override {
10177 PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::LIGHT);
10178 }
Chris Yee2b1e5c2021-03-10 22:45:12 -080010179};
10180
Chris Ye85758332021-05-16 23:05:17 -070010181TEST_F(LightControllerTest, MonoLight) {
10182 RawLightInfo infoMono = {.id = 1,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010183 .name = "mono_light",
Chris Ye85758332021-05-16 23:05:17 -070010184 .maxBrightness = 255,
10185 .flags = InputLightClass::BRIGHTNESS,
10186 .path = ""};
10187 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010188
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010189 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010190 InputDeviceInfo info;
10191 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010192 std::vector<InputDeviceLightInfo> lights = info.getLights();
10193 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010194 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10195 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10196
10197 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_BRIGHTNESS));
10198 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_BRIGHTNESS);
10199}
10200
DingYong99f2c3c2023-12-20 15:46:06 +080010201TEST_F(LightControllerTest, MonoKeyboardMuteLight) {
10202 RawLightInfo infoMono = {.id = 1,
10203 .name = "mono_keyboard_mute",
10204 .maxBrightness = 255,
10205 .flags = InputLightClass::BRIGHTNESS |
10206 InputLightClass::KEYBOARD_MIC_MUTE,
10207 .path = ""};
10208 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10209
10210 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10211 std::list<NotifyArgs> unused =
10212 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10213 /*changes=*/{});
10214
10215 InputDeviceInfo info;
10216 controller.populateDeviceInfo(&info);
10217 std::vector<InputDeviceLightInfo> lights = info.getLights();
10218 ASSERT_EQ(1U, lights.size());
10219 ASSERT_EQ(InputDeviceLightType::KEYBOARD_MIC_MUTE, lights[0].type);
10220 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10221}
10222
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010223TEST_F(LightControllerTest, MonoKeyboardBacklight) {
10224 RawLightInfo infoMono = {.id = 1,
10225 .name = "mono_keyboard_backlight",
10226 .maxBrightness = 255,
10227 .flags = InputLightClass::BRIGHTNESS |
10228 InputLightClass::KEYBOARD_BACKLIGHT,
10229 .path = ""};
10230 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10231
10232 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10233 InputDeviceInfo info;
10234 controller.populateDeviceInfo(&info);
10235 std::vector<InputDeviceLightInfo> lights = info.getLights();
10236 ASSERT_EQ(1U, lights.size());
10237 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10238 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010239
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010240 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_BRIGHTNESS));
10241 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_BRIGHTNESS);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010242}
10243
Vaibhav Devmurari16c24192023-05-04 15:20:12 +000010244TEST_F(LightControllerTest, Ignore_MonoLight_WithPreferredBacklightLevels) {
10245 RawLightInfo infoMono = {.id = 1,
10246 .name = "mono_light",
10247 .maxBrightness = 255,
10248 .flags = InputLightClass::BRIGHTNESS,
10249 .path = ""};
10250 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10251 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10252 "0,100,200");
10253
10254 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10255 std::list<NotifyArgs> unused =
10256 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10257 /*changes=*/{});
10258
10259 InputDeviceInfo info;
10260 controller.populateDeviceInfo(&info);
10261 std::vector<InputDeviceLightInfo> lights = info.getLights();
10262 ASSERT_EQ(1U, lights.size());
10263 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10264}
10265
10266TEST_F(LightControllerTest, KeyboardBacklight_WithNoPreferredBacklightLevels) {
10267 RawLightInfo infoMono = {.id = 1,
10268 .name = "mono_keyboard_backlight",
10269 .maxBrightness = 255,
10270 .flags = InputLightClass::BRIGHTNESS |
10271 InputLightClass::KEYBOARD_BACKLIGHT,
10272 .path = ""};
10273 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10274
10275 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10276 std::list<NotifyArgs> unused =
10277 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10278 /*changes=*/{});
10279
10280 InputDeviceInfo info;
10281 controller.populateDeviceInfo(&info);
10282 std::vector<InputDeviceLightInfo> lights = info.getLights();
10283 ASSERT_EQ(1U, lights.size());
10284 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10285}
10286
10287TEST_F(LightControllerTest, KeyboardBacklight_WithPreferredBacklightLevels) {
10288 RawLightInfo infoMono = {.id = 1,
10289 .name = "mono_keyboard_backlight",
10290 .maxBrightness = 255,
10291 .flags = InputLightClass::BRIGHTNESS |
10292 InputLightClass::KEYBOARD_BACKLIGHT,
10293 .path = ""};
10294 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10295 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10296 "0,100,200");
10297
10298 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10299 std::list<NotifyArgs> unused =
10300 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10301 /*changes=*/{});
10302
10303 InputDeviceInfo info;
10304 controller.populateDeviceInfo(&info);
10305 std::vector<InputDeviceLightInfo> lights = info.getLights();
10306 ASSERT_EQ(1U, lights.size());
10307 ASSERT_EQ(3U, lights[0].preferredBrightnessLevels.size());
10308 std::set<BrightnessLevel>::iterator it = lights[0].preferredBrightnessLevels.begin();
10309 ASSERT_EQ(BrightnessLevel(0), *it);
10310 std::advance(it, 1);
10311 ASSERT_EQ(BrightnessLevel(100), *it);
10312 std::advance(it, 1);
10313 ASSERT_EQ(BrightnessLevel(200), *it);
10314}
10315
10316TEST_F(LightControllerTest, KeyboardBacklight_WithWrongPreferredBacklightLevels) {
10317 RawLightInfo infoMono = {.id = 1,
10318 .name = "mono_keyboard_backlight",
10319 .maxBrightness = 255,
10320 .flags = InputLightClass::BRIGHTNESS |
10321 InputLightClass::KEYBOARD_BACKLIGHT,
10322 .path = ""};
10323 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10324 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10325 "0,100,200,300,400,500");
10326
10327 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10328 std::list<NotifyArgs> unused =
10329 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10330 /*changes=*/{});
10331
10332 InputDeviceInfo info;
10333 controller.populateDeviceInfo(&info);
10334 std::vector<InputDeviceLightInfo> lights = info.getLights();
10335 ASSERT_EQ(1U, lights.size());
10336 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10337}
10338
Chris Yee2b1e5c2021-03-10 22:45:12 -080010339TEST_F(LightControllerTest, RGBLight) {
10340 RawLightInfo infoRed = {.id = 1,
10341 .name = "red",
10342 .maxBrightness = 255,
10343 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED,
10344 .path = ""};
10345 RawLightInfo infoGreen = {.id = 2,
10346 .name = "green",
10347 .maxBrightness = 255,
10348 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN,
10349 .path = ""};
10350 RawLightInfo infoBlue = {.id = 3,
10351 .name = "blue",
10352 .maxBrightness = 255,
10353 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE,
10354 .path = ""};
10355 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10356 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10357 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10358
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010359 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010360 InputDeviceInfo info;
10361 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010362 std::vector<InputDeviceLightInfo> lights = info.getLights();
10363 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010364 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10365 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10366 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10367
10368 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10369 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10370}
10371
10372TEST_F(LightControllerTest, CorrectRGBKeyboardBacklight) {
10373 RawLightInfo infoRed = {.id = 1,
10374 .name = "red_keyboard_backlight",
10375 .maxBrightness = 255,
10376 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED |
10377 InputLightClass::KEYBOARD_BACKLIGHT,
10378 .path = ""};
10379 RawLightInfo infoGreen = {.id = 2,
10380 .name = "green_keyboard_backlight",
10381 .maxBrightness = 255,
10382 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN |
10383 InputLightClass::KEYBOARD_BACKLIGHT,
10384 .path = ""};
10385 RawLightInfo infoBlue = {.id = 3,
10386 .name = "blue_keyboard_backlight",
10387 .maxBrightness = 255,
10388 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE |
10389 InputLightClass::KEYBOARD_BACKLIGHT,
10390 .path = ""};
10391 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10392 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10393 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10394
10395 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10396 InputDeviceInfo info;
10397 controller.populateDeviceInfo(&info);
10398 std::vector<InputDeviceLightInfo> lights = info.getLights();
10399 ASSERT_EQ(1U, lights.size());
10400 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10401 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10402 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10403
10404 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10405 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10406}
10407
10408TEST_F(LightControllerTest, IncorrectRGBKeyboardBacklight) {
10409 RawLightInfo infoRed = {.id = 1,
10410 .name = "red",
10411 .maxBrightness = 255,
10412 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED,
10413 .path = ""};
10414 RawLightInfo infoGreen = {.id = 2,
10415 .name = "green",
10416 .maxBrightness = 255,
10417 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN,
10418 .path = ""};
10419 RawLightInfo infoBlue = {.id = 3,
10420 .name = "blue",
10421 .maxBrightness = 255,
10422 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE,
10423 .path = ""};
10424 RawLightInfo infoGlobal = {.id = 3,
10425 .name = "global_keyboard_backlight",
10426 .maxBrightness = 255,
10427 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GLOBAL |
10428 InputLightClass::KEYBOARD_BACKLIGHT,
10429 .path = ""};
10430 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10431 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10432 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10433 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoGlobal));
10434
10435 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10436 InputDeviceInfo info;
10437 controller.populateDeviceInfo(&info);
10438 std::vector<InputDeviceLightInfo> lights = info.getLights();
10439 ASSERT_EQ(1U, lights.size());
10440 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10441 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10442 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010443
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010444 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10445 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010446}
10447
10448TEST_F(LightControllerTest, MultiColorRGBLight) {
10449 RawLightInfo infoColor = {.id = 1,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010450 .name = "multi_color",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010451 .maxBrightness = 255,
10452 .flags = InputLightClass::BRIGHTNESS |
10453 InputLightClass::MULTI_INTENSITY |
10454 InputLightClass::MULTI_INDEX,
10455 .path = ""};
10456
10457 mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
10458
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010459 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010460 InputDeviceInfo info;
10461 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010462 std::vector<InputDeviceLightInfo> lights = info.getLights();
10463 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010464 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10465 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10466 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10467
10468 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10469 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10470}
10471
10472TEST_F(LightControllerTest, MultiColorRGBKeyboardBacklight) {
10473 RawLightInfo infoColor = {.id = 1,
10474 .name = "multi_color_keyboard_backlight",
10475 .maxBrightness = 255,
10476 .flags = InputLightClass::BRIGHTNESS |
10477 InputLightClass::MULTI_INTENSITY |
10478 InputLightClass::MULTI_INDEX |
10479 InputLightClass::KEYBOARD_BACKLIGHT,
10480 .path = ""};
10481
10482 mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
10483
10484 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10485 InputDeviceInfo info;
10486 controller.populateDeviceInfo(&info);
10487 std::vector<InputDeviceLightInfo> lights = info.getLights();
10488 ASSERT_EQ(1U, lights.size());
10489 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10490 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10491 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010492
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010493 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10494 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010495}
10496
Josep del Rioa1046a82023-08-24 19:57:27 +000010497TEST_F(LightControllerTest, SonyPlayerIdLight) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010498 RawLightInfo info1 = {.id = 1,
Josep del Rioa1046a82023-08-24 19:57:27 +000010499 .name = "sony1",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010500 .maxBrightness = 255,
10501 .flags = InputLightClass::BRIGHTNESS,
10502 .path = ""};
10503 RawLightInfo info2 = {.id = 2,
Josep del Rioa1046a82023-08-24 19:57:27 +000010504 .name = "sony2",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010505 .maxBrightness = 255,
10506 .flags = InputLightClass::BRIGHTNESS,
10507 .path = ""};
10508 RawLightInfo info3 = {.id = 3,
Josep del Rioa1046a82023-08-24 19:57:27 +000010509 .name = "sony3",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010510 .maxBrightness = 255,
10511 .flags = InputLightClass::BRIGHTNESS,
10512 .path = ""};
10513 RawLightInfo info4 = {.id = 4,
Josep del Rioa1046a82023-08-24 19:57:27 +000010514 .name = "sony4",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010515 .maxBrightness = 255,
10516 .flags = InputLightClass::BRIGHTNESS,
10517 .path = ""};
10518 mFakeEventHub->addRawLightInfo(info1.id, std::move(info1));
10519 mFakeEventHub->addRawLightInfo(info2.id, std::move(info2));
10520 mFakeEventHub->addRawLightInfo(info3.id, std::move(info3));
10521 mFakeEventHub->addRawLightInfo(info4.id, std::move(info4));
10522
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010523 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010524 InputDeviceInfo info;
10525 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010526 std::vector<InputDeviceLightInfo> lights = info.getLights();
10527 ASSERT_EQ(1U, lights.size());
Josep del Rioa1046a82023-08-24 19:57:27 +000010528 ASSERT_STREQ("sony", lights[0].name.c_str());
10529 ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
10530 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10531 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10532
10533 ASSERT_FALSE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10534 ASSERT_TRUE(controller.setLightPlayerId(lights[0].id, LIGHT_PLAYER_ID));
10535 ASSERT_EQ(controller.getLightPlayerId(lights[0].id).value_or(-1), LIGHT_PLAYER_ID);
10536 ASSERT_STREQ("sony", lights[0].name.c_str());
10537}
10538
10539TEST_F(LightControllerTest, PlayerIdLight) {
10540 RawLightInfo info1 = {.id = 1,
10541 .name = "player-1",
10542 .maxBrightness = 255,
10543 .flags = InputLightClass::BRIGHTNESS,
10544 .path = ""};
10545 RawLightInfo info2 = {.id = 2,
10546 .name = "player-2",
10547 .maxBrightness = 255,
10548 .flags = InputLightClass::BRIGHTNESS,
10549 .path = ""};
10550 RawLightInfo info3 = {.id = 3,
10551 .name = "player-3",
10552 .maxBrightness = 255,
10553 .flags = InputLightClass::BRIGHTNESS,
10554 .path = ""};
10555 RawLightInfo info4 = {.id = 4,
10556 .name = "player-4",
10557 .maxBrightness = 255,
10558 .flags = InputLightClass::BRIGHTNESS,
10559 .path = ""};
10560 mFakeEventHub->addRawLightInfo(info1.id, std::move(info1));
10561 mFakeEventHub->addRawLightInfo(info2.id, std::move(info2));
10562 mFakeEventHub->addRawLightInfo(info3.id, std::move(info3));
10563 mFakeEventHub->addRawLightInfo(info4.id, std::move(info4));
10564
10565 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10566 InputDeviceInfo info;
10567 controller.populateDeviceInfo(&info);
10568 std::vector<InputDeviceLightInfo> lights = info.getLights();
10569 ASSERT_EQ(1U, lights.size());
10570 ASSERT_STREQ("player", lights[0].name.c_str());
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010571 ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010572 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10573 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010574
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010575 ASSERT_FALSE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10576 ASSERT_TRUE(controller.setLightPlayerId(lights[0].id, LIGHT_PLAYER_ID));
10577 ASSERT_EQ(controller.getLightPlayerId(lights[0].id).value_or(-1), LIGHT_PLAYER_ID);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010578}
10579
Michael Wrightd02c5b62014-02-10 15:10:22 -080010580} // namespace android