blob: 19b738ea9d975c5d38b9990fcca7cb5c10e8f510 [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
Yanye Li81a590c2024-10-22 19:25:54 +00001395TEST_F(InputReaderTest, SetPowerWakeUp) {
1396 ASSERT_NO_FATAL_FAILURE(addDevice(1, "1st", InputDeviceClass::KEYBOARD, nullptr));
1397 ASSERT_NO_FATAL_FAILURE(addDevice(2, "2nd", InputDeviceClass::KEYBOARD, nullptr));
1398 ASSERT_NO_FATAL_FAILURE(addDevice(3, "3rd", InputDeviceClass::KEYBOARD, nullptr));
1399
1400 ASSERT_EQ(mFakeEventHub->fakeReadKernelWakeup(1), false);
1401
1402 ASSERT_TRUE(mFakeEventHub->setKernelWakeEnabled(2, true));
1403 ASSERT_EQ(mFakeEventHub->fakeReadKernelWakeup(2), true);
1404
1405 ASSERT_TRUE(mFakeEventHub->setKernelWakeEnabled(3, false));
1406 ASSERT_EQ(mFakeEventHub->fakeReadKernelWakeup(3), false);
1407}
1408
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001409// --- InputReaderIntegrationTest ---
1410
1411// These tests create and interact with the InputReader only through its interface.
1412// The InputReader is started during SetUp(), which starts its processing in its own
1413// thread. The tests use linux uinput to emulate input devices.
1414// NOTE: Interacting with the physical device while these tests are running may cause
1415// the tests to fail.
1416class InputReaderIntegrationTest : public testing::Test {
1417protected:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001418 std::unique_ptr<TestInputListener> mTestListener;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001419 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001420 std::unique_ptr<InputReaderInterface> mReader;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001421
Prabir Pradhanafb7d612024-01-08 22:45:24 +00001422 constexpr static auto EVENT_HAPPENED_TIMEOUT = 2000ms;
1423 constexpr static auto EVENT_DID_NOT_HAPPEN_TIMEOUT = 30ms;
1424
Chris Yea52ade12020-08-27 16:49:20 -07001425 void SetUp() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001426#if !defined(__ANDROID__)
1427 GTEST_SKIP();
1428#endif
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001429 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001430
Arpit Singh440bf652023-08-09 09:23:43 +00001431 setupInputReader();
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001432 }
1433
Chris Yea52ade12020-08-27 16:49:20 -07001434 void TearDown() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001435#if !defined(__ANDROID__)
1436 return;
1437#endif
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001438 ASSERT_EQ(mReader->stop(), OK);
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001439 mReader.reset();
1440 mTestListener.reset();
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001441 mFakePolicy.clear();
1442 }
Prabir Pradhanda20b172022-09-26 17:01:18 +00001443
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001444 std::optional<InputDeviceInfo> waitForDevice(const std::string& deviceName) {
1445 std::chrono::time_point start = std::chrono::steady_clock::now();
1446 while (true) {
1447 const std::vector<InputDeviceInfo> inputDevices = mFakePolicy->getInputDevices();
1448 const auto& it = std::find_if(inputDevices.begin(), inputDevices.end(),
1449 [&deviceName](const InputDeviceInfo& info) {
1450 return info.getIdentifier().name == deviceName;
1451 });
1452 if (it != inputDevices.end()) {
1453 return std::make_optional(*it);
1454 }
1455 std::this_thread::sleep_for(1ms);
1456 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
1457 if (elapsed > 5s) {
1458 return {};
1459 }
1460 }
Prabir Pradhanda20b172022-09-26 17:01:18 +00001461 }
Arpit Singh440bf652023-08-09 09:23:43 +00001462
1463 void setupInputReader() {
Prabir Pradhanafb7d612024-01-08 22:45:24 +00001464 mTestListener = std::make_unique<TestInputListener>(EVENT_HAPPENED_TIMEOUT,
1465 EVENT_DID_NOT_HAPPEN_TIMEOUT);
Arpit Singh440bf652023-08-09 09:23:43 +00001466
1467 mReader = std::make_unique<InputReader>(std::make_shared<EventHub>(), mFakePolicy,
1468 *mTestListener);
1469 ASSERT_EQ(mReader->start(), OK);
1470
1471 // Since this test is run on a real device, all the input devices connected
1472 // to the test device will show up in mReader. We wait for those input devices to
1473 // show up before beginning the tests.
Arpit Singh440bf652023-08-09 09:23:43 +00001474 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyInputDevicesChangedWasCalled());
Vaibhav Devmuraric109d812024-07-10 14:21:27 +00001475 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Arpit Singh440bf652023-08-09 09:23:43 +00001476 }
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001477};
1478
1479TEST_F(InputReaderIntegrationTest, TestInvalidDevice) {
1480 // An invalid input device that is only used for this test.
1481 class InvalidUinputDevice : public UinputDevice {
1482 public:
Harry Cutts33476232023-01-30 19:57:29 +00001483 InvalidUinputDevice() : UinputDevice("Invalid Device", /*productId=*/99) {}
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001484
1485 private:
1486 void configureDevice(int fd, uinput_user_dev* device) override {}
1487 };
1488
1489 const size_t numDevices = mFakePolicy->getInputDevices().size();
1490
1491 // UinputDevice does not set any event or key bits, so InputReader should not
1492 // consider it as a valid device.
1493 std::unique_ptr<UinputDevice> invalidDevice = createUinputDevice<InvalidUinputDevice>();
1494 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesNotChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001495 ASSERT_EQ(numDevices, mFakePolicy->getInputDevices().size());
1496
1497 invalidDevice.reset();
1498 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesNotChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001499 ASSERT_EQ(numDevices, mFakePolicy->getInputDevices().size());
1500}
1501
1502TEST_F(InputReaderIntegrationTest, AddNewDevice) {
1503 const size_t initialNumDevices = mFakePolicy->getInputDevices().size();
1504
1505 std::unique_ptr<UinputHomeKey> keyboard = createUinputDevice<UinputHomeKey>();
1506 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001507 ASSERT_EQ(initialNumDevices + 1, mFakePolicy->getInputDevices().size());
1508
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001509 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001510 ASSERT_TRUE(device.has_value());
1511 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, device->getKeyboardType());
1512 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources());
1513 ASSERT_EQ(0U, device->getMotionRanges().size());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001514
1515 keyboard.reset();
1516 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001517 ASSERT_EQ(initialNumDevices, mFakePolicy->getInputDevices().size());
1518}
1519
1520TEST_F(InputReaderIntegrationTest, SendsEventsToInputListener) {
1521 std::unique_ptr<UinputHomeKey> keyboard = createUinputDevice<UinputHomeKey>();
1522 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1523
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001524 NotifyKeyArgs keyArgs;
1525 keyboard->pressAndReleaseHomeKey();
1526 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs));
1527 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001528 ASSERT_LE(keyArgs.eventTime, keyArgs.readTime);
Liana Kazanova5b8217b2024-07-18 17:44:51 +00001529
1530 int32_t prevId = keyArgs.id;
1531 nsecs_t prevTimestamp = keyArgs.eventTime;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001532
1533 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs));
1534 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
Garfield Tan1c7bc862020-01-28 13:24:04 -08001535 ASSERT_NE(prevId, keyArgs.id);
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001536 ASSERT_LE(prevTimestamp, keyArgs.eventTime);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001537 ASSERT_LE(keyArgs.eventTime, keyArgs.readTime);
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001538}
Michael Wrightd02c5b62014-02-10 15:10:22 -08001539
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001540TEST_F(InputReaderIntegrationTest, ExternalStylusesButtons) {
1541 std::unique_ptr<UinputExternalStylus> stylus = createUinputDevice<UinputExternalStylus>();
1542 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1543
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001544 const auto device = waitForDevice(stylus->getName());
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001545 ASSERT_TRUE(device.has_value());
1546
Prabir Pradhana3621852022-10-14 18:57:23 +00001547 // An external stylus with buttons should also be recognized as a keyboard.
1548 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_STYLUS, device->getSources())
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001549 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1550 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, device->getKeyboardType());
1551
1552 const auto DOWN =
1553 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD));
1554 const auto UP = AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD));
1555
1556 stylus->pressAndReleaseKey(BTN_STYLUS);
1557 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1558 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
1559 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1560 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
1561
1562 stylus->pressAndReleaseKey(BTN_STYLUS2);
1563 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1564 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_SECONDARY))));
1565 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1566 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_SECONDARY))));
1567
1568 stylus->pressAndReleaseKey(BTN_STYLUS3);
1569 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1570 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_TERTIARY))));
1571 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1572 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_TERTIARY))));
1573}
1574
Prabir Pradhan3c28b942023-08-18 20:02:01 +00001575TEST_F(InputReaderIntegrationTest, KeyboardWithStylusButtons) {
1576 std::unique_ptr<UinputKeyboard> keyboard =
1577 createUinputDevice<UinputKeyboard>("KeyboardWithStylusButtons", /*productId=*/99,
1578 std::initializer_list<int>{KEY_Q, KEY_W, KEY_E,
1579 KEY_R, KEY_T, KEY_Y,
1580 BTN_STYLUS, BTN_STYLUS2,
1581 BTN_STYLUS3});
1582 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1583
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001584 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhan3c28b942023-08-18 20:02:01 +00001585 ASSERT_TRUE(device.has_value());
1586
1587 // An alphabetical keyboard that reports stylus buttons should not be recognized as a stylus.
1588 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources())
1589 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1590 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, device->getKeyboardType());
1591}
1592
Prabir Pradhan37a819b2023-08-22 23:20:16 +00001593TEST_F(InputReaderIntegrationTest, HidUsageKeyboardIsNotAStylus) {
1594 // Create a Uinput keyboard that simulates a keyboard that can report HID usage codes. The
1595 // hid-input driver reports HID usage codes using the value for EV_MSC MSC_SCAN event.
1596 std::unique_ptr<UinputKeyboardWithHidUsage> keyboard =
1597 createUinputDevice<UinputKeyboardWithHidUsage>(
1598 std::initializer_list<int>{KEY_VOLUMEUP, KEY_VOLUMEDOWN});
1599 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1600
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001601 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhan37a819b2023-08-22 23:20:16 +00001602 ASSERT_TRUE(device.has_value());
1603
1604 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources())
1605 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1606
1607 // If a device supports reporting HID usage codes, it shouldn't automatically support
1608 // stylus keys.
1609 const std::vector<int> keycodes{AKEYCODE_STYLUS_BUTTON_PRIMARY};
1610 uint8_t outFlags[] = {0};
1611 ASSERT_TRUE(mReader->hasKeys(device->getId(), AINPUT_SOURCE_KEYBOARD, keycodes, outFlags));
1612 ASSERT_EQ(0, outFlags[0]) << "Keyboard should not have stylus button";
1613}
1614
Siarhei Vishniakoua0d2b802020-05-13 14:00:31 -07001615/**
1616 * The Steam controller sends BTN_GEAR_DOWN and BTN_GEAR_UP for the two "paddle" buttons
1617 * on the back. In this test, we make sure that BTN_GEAR_DOWN / BTN_WHEEL and BTN_GEAR_UP
1618 * are passed to the listener.
1619 */
1620static_assert(BTN_GEAR_DOWN == BTN_WHEEL);
1621TEST_F(InputReaderIntegrationTest, SendsGearDownAndUpToInputListener) {
1622 std::unique_ptr<UinputSteamController> controller = createUinputDevice<UinputSteamController>();
1623 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1624 NotifyKeyArgs keyArgs;
1625
1626 controller->pressAndReleaseKey(BTN_GEAR_DOWN);
1627 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_DOWN
1628 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_UP
1629 ASSERT_EQ(BTN_GEAR_DOWN, keyArgs.scanCode);
1630
1631 controller->pressAndReleaseKey(BTN_GEAR_UP);
1632 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_DOWN
1633 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_UP
1634 ASSERT_EQ(BTN_GEAR_UP, keyArgs.scanCode);
1635}
1636
Prabir Pradhan484d55a2022-10-14 23:17:16 +00001637// --- TouchIntegrationTest ---
1638
Arpit Singh440bf652023-08-09 09:23:43 +00001639class BaseTouchIntegrationTest : public InputReaderIntegrationTest {
Arthur Hungaab25622020-01-16 11:22:11 +08001640protected:
Arthur Hungaab25622020-01-16 11:22:11 +08001641 const std::string UNIQUE_ID = "local:0";
1642
Chris Yea52ade12020-08-27 16:49:20 -07001643 void SetUp() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001644#if !defined(__ANDROID__)
1645 GTEST_SKIP();
1646#endif
Arthur Hungaab25622020-01-16 11:22:11 +08001647 InputReaderIntegrationTest::SetUp();
1648 // At least add an internal display.
Michael Wrighta9cf4192022-12-01 23:46:39 +00001649 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
1650 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Arthur Hungaab25622020-01-16 11:22:11 +08001651
1652 mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT));
1653 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001654 const auto info = waitForDevice(mDevice->getName());
Prabir Pradhanda20b172022-09-26 17:01:18 +00001655 ASSERT_TRUE(info);
1656 mDeviceInfo = *info;
Arthur Hungaab25622020-01-16 11:22:11 +08001657 }
1658
Linnan Li13bf76a2024-05-05 19:18:02 +08001659 void setDisplayInfoAndReconfigure(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
Michael Wrighta9cf4192022-12-01 23:46:39 +00001660 ui::Rotation orientation, const std::string& uniqueId,
Arthur Hungaab25622020-01-16 11:22:11 +08001661 std::optional<uint8_t> physicalPort,
1662 ViewportType viewportType) {
Harry Cutts33476232023-01-30 19:57:29 +00001663 mFakePolicy->addDisplayViewport(displayId, width, height, orientation, /*isActive=*/true,
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00001664 uniqueId, physicalPort, viewportType);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001665 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hungaab25622020-01-16 11:22:11 +08001666 }
1667
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001668 void assertReceivedMotion(int32_t action, const std::vector<Point>& points) {
1669 NotifyMotionArgs args;
1670 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1671 EXPECT_EQ(action, args.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07001672 ASSERT_EQ(points.size(), args.getPointerCount());
1673 for (size_t i = 0; i < args.getPointerCount(); i++) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001674 EXPECT_EQ(points[i].x, args.pointerCoords[i].getX());
1675 EXPECT_EQ(points[i].y, args.pointerCoords[i].getY());
1676 }
1677 }
1678
Arthur Hungaab25622020-01-16 11:22:11 +08001679 std::unique_ptr<UinputTouchScreen> mDevice;
Prabir Pradhanda20b172022-09-26 17:01:18 +00001680 InputDeviceInfo mDeviceInfo;
Arthur Hungaab25622020-01-16 11:22:11 +08001681};
1682
Arpit Singh440bf652023-08-09 09:23:43 +00001683enum class TouchIntegrationTestDisplays { DISPLAY_INTERNAL, DISPLAY_INPUT_PORT, DISPLAY_UNIQUE_ID };
1684
1685class TouchIntegrationTest : public BaseTouchIntegrationTest,
1686 public testing::WithParamInterface<TouchIntegrationTestDisplays> {
1687protected:
1688 static constexpr std::optional<uint8_t> DISPLAY_PORT = 0;
1689 const std::string INPUT_PORT = "uinput_touch/input0";
1690
1691 void SetUp() override {
1692#if !defined(__ANDROID__)
1693 GTEST_SKIP();
1694#endif
1695 if (GetParam() == TouchIntegrationTestDisplays::DISPLAY_INTERNAL) {
1696 BaseTouchIntegrationTest::SetUp();
1697 return;
1698 }
1699
1700 // setup policy with a input-port or UniqueId association to the display
1701 bool isInputPortAssociation =
1702 GetParam() == TouchIntegrationTestDisplays::DISPLAY_INPUT_PORT;
1703
1704 mFakePolicy = sp<FakeInputReaderPolicy>::make();
1705 if (isInputPortAssociation) {
1706 mFakePolicy->addInputPortAssociation(INPUT_PORT, DISPLAY_PORT.value());
1707 } else {
1708 mFakePolicy->addInputUniqueIdAssociation(INPUT_PORT, UNIQUE_ID);
1709 }
Arpit Singh440bf652023-08-09 09:23:43 +00001710
1711 InputReaderIntegrationTest::setupInputReader();
1712
1713 mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT),
1714 INPUT_PORT);
1715 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1716
1717 // Add a display linked to a physical port or UniqueId.
1718 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
1719 UNIQUE_ID, isInputPortAssociation ? DISPLAY_PORT : NO_PORT,
1720 ViewportType::INTERNAL);
1721 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001722 const auto info = waitForDevice(mDevice->getName());
Arpit Singh440bf652023-08-09 09:23:43 +00001723 ASSERT_TRUE(info);
1724 mDeviceInfo = *info;
1725 }
1726};
1727
1728TEST_P(TouchIntegrationTest, MultiTouchDeviceSource) {
Prabir Pradhanf9a41282022-10-25 17:15:50 +00001729 // The UinputTouchScreen is an MT device that supports MT_TOOL_TYPE and also supports stylus
1730 // buttons. It should show up as a touchscreen, stylus, and keyboard (for reporting button
1731 // presses).
1732 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD,
1733 mDeviceInfo.getSources());
1734}
1735
Arpit Singh440bf652023-08-09 09:23:43 +00001736TEST_P(TouchIntegrationTest, InputEvent_ProcessSingleTouch) {
Arthur Hungaab25622020-01-16 11:22:11 +08001737 NotifyMotionArgs args;
1738 const Point centerPoint = mDevice->getCenterPoint();
1739
1740 // ACTION_DOWN
Arthur Hung9ad18942021-06-19 02:04:46 +00001741 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001742 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001743 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001744 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1745 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1746
1747 // ACTION_MOVE
1748 mDevice->sendMove(centerPoint + Point(1, 1));
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001749 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001750 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1751 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1752
1753 // ACTION_UP
1754 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001755 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001756 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1757 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
1758}
1759
Arpit Singh440bf652023-08-09 09:23:43 +00001760TEST_P(TouchIntegrationTest, InputEvent_ProcessMultiTouch) {
Arthur Hungaab25622020-01-16 11:22:11 +08001761 NotifyMotionArgs args;
1762 const Point centerPoint = mDevice->getCenterPoint();
1763
1764 // ACTION_DOWN
Arthur Hung9ad18942021-06-19 02:04:46 +00001765 mDevice->sendSlot(FIRST_SLOT);
1766 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001767 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001768 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001769 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1770 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1771
1772 // ACTION_POINTER_DOWN (Second slot)
1773 const Point secondPoint = centerPoint + Point(100, 100);
1774 mDevice->sendSlot(SECOND_SLOT);
1775 mDevice->sendTrackingId(SECOND_TRACKING_ID);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001776 mDevice->sendDown(secondPoint);
1777 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001778 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001779 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001780
1781 // ACTION_MOVE (Second slot)
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001782 mDevice->sendMove(secondPoint + Point(1, 1));
1783 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001784 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1785 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1786
1787 // ACTION_POINTER_UP (Second slot)
arthurhungcc7f9802020-04-30 17:55:40 +08001788 mDevice->sendPointerUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001789 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001790 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001791 ASSERT_EQ(ACTION_POINTER_1_UP, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001792
1793 // ACTION_UP
1794 mDevice->sendSlot(FIRST_SLOT);
1795 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001796 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001797 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1798 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
1799}
1800
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001801/**
1802 * What happens when a pointer goes up while another pointer moves in the same frame? Are POINTER_UP
1803 * events guaranteed to contain the same data as a preceding MOVE, or can they contain different
1804 * data?
1805 * In this test, we try to send a change in coordinates in Pointer 0 in the same frame as the
1806 * liftoff of Pointer 1. We check that POINTER_UP event is generated first, and the MOVE event
1807 * for Pointer 0 only is generated after.
1808 * Suppose we are only interested in learning the movement of Pointer 0. If we only observe MOVE
1809 * events, we will not miss any information.
1810 * Even though the Pointer 1 up event contains updated Pointer 0 coordinates, there is another MOVE
1811 * event generated afterwards that contains the newest movement of pointer 0.
1812 * This is important for palm rejection. If there is a subsequent InputListener stage that detects
1813 * palms, and wants to cancel Pointer 1, then it is safe to simply drop POINTER_1_UP event without
1814 * losing information about non-palm pointers.
1815 */
Arpit Singh440bf652023-08-09 09:23:43 +00001816TEST_P(TouchIntegrationTest, MultiTouch_PointerMoveAndSecondPointerUp) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001817 NotifyMotionArgs args;
1818 const Point centerPoint = mDevice->getCenterPoint();
1819
1820 // ACTION_DOWN
1821 mDevice->sendSlot(FIRST_SLOT);
1822 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1823 mDevice->sendDown(centerPoint);
1824 mDevice->sendSync();
1825 assertReceivedMotion(AMOTION_EVENT_ACTION_DOWN, {centerPoint});
1826
1827 // ACTION_POINTER_DOWN (Second slot)
1828 const Point secondPoint = centerPoint + Point(100, 100);
1829 mDevice->sendSlot(SECOND_SLOT);
1830 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1831 mDevice->sendDown(secondPoint);
1832 mDevice->sendSync();
1833 assertReceivedMotion(ACTION_POINTER_1_DOWN, {centerPoint, secondPoint});
1834
1835 // ACTION_MOVE (First slot)
1836 mDevice->sendSlot(FIRST_SLOT);
1837 mDevice->sendMove(centerPoint + Point(5, 5));
1838 // ACTION_POINTER_UP (Second slot)
1839 mDevice->sendSlot(SECOND_SLOT);
1840 mDevice->sendPointerUp();
1841 // Send a single sync for the above 2 pointer updates
1842 mDevice->sendSync();
1843
1844 // First, we should get POINTER_UP for the second pointer
1845 assertReceivedMotion(ACTION_POINTER_1_UP,
1846 {/*first pointer */ centerPoint + Point(5, 5),
1847 /*second pointer*/ secondPoint});
1848
1849 // Next, the MOVE event for the first pointer
1850 assertReceivedMotion(AMOTION_EVENT_ACTION_MOVE, {centerPoint + Point(5, 5)});
1851}
1852
1853/**
1854 * Similar scenario as above. The difference is that when the second pointer goes up, it will first
1855 * move, and then it will go up, all in the same frame.
1856 * In this scenario, the movement of the second pointer just prior to liftoff is ignored, and never
1857 * gets sent to the listener.
1858 */
Arpit Singh440bf652023-08-09 09:23:43 +00001859TEST_P(TouchIntegrationTest, MultiTouch_PointerMoveAndSecondPointerMoveAndUp) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001860 NotifyMotionArgs args;
1861 const Point centerPoint = mDevice->getCenterPoint();
1862
1863 // ACTION_DOWN
1864 mDevice->sendSlot(FIRST_SLOT);
1865 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1866 mDevice->sendDown(centerPoint);
1867 mDevice->sendSync();
1868 assertReceivedMotion(AMOTION_EVENT_ACTION_DOWN, {centerPoint});
1869
1870 // ACTION_POINTER_DOWN (Second slot)
1871 const Point secondPoint = centerPoint + Point(100, 100);
1872 mDevice->sendSlot(SECOND_SLOT);
1873 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1874 mDevice->sendDown(secondPoint);
1875 mDevice->sendSync();
1876 assertReceivedMotion(ACTION_POINTER_1_DOWN, {centerPoint, secondPoint});
1877
1878 // ACTION_MOVE (First slot)
1879 mDevice->sendSlot(FIRST_SLOT);
1880 mDevice->sendMove(centerPoint + Point(5, 5));
1881 // ACTION_POINTER_UP (Second slot)
1882 mDevice->sendSlot(SECOND_SLOT);
1883 mDevice->sendMove(secondPoint + Point(6, 6));
1884 mDevice->sendPointerUp();
1885 // Send a single sync for the above 2 pointer updates
1886 mDevice->sendSync();
1887
1888 // First, we should get POINTER_UP for the second pointer
1889 // The movement of the second pointer during the liftoff frame is ignored.
1890 // The coordinates 'secondPoint + Point(6, 6)' are never sent to the listener.
1891 assertReceivedMotion(ACTION_POINTER_1_UP,
1892 {/*first pointer */ centerPoint + Point(5, 5),
1893 /*second pointer*/ secondPoint});
1894
1895 // Next, the MOVE event for the first pointer
1896 assertReceivedMotion(AMOTION_EVENT_ACTION_MOVE, {centerPoint + Point(5, 5)});
1897}
1898
Arpit Singh440bf652023-08-09 09:23:43 +00001899TEST_P(TouchIntegrationTest, InputEvent_ProcessPalm) {
Arthur Hungaab25622020-01-16 11:22:11 +08001900 NotifyMotionArgs args;
1901 const Point centerPoint = mDevice->getCenterPoint();
1902
1903 // ACTION_DOWN
arthurhungcc7f9802020-04-30 17:55:40 +08001904 mDevice->sendSlot(FIRST_SLOT);
1905 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001906 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001907 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001908 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1909 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1910
arthurhungcc7f9802020-04-30 17:55:40 +08001911 // ACTION_POINTER_DOWN (second slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001912 const Point secondPoint = centerPoint + Point(100, 100);
1913 mDevice->sendSlot(SECOND_SLOT);
1914 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1915 mDevice->sendDown(secondPoint);
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_DOWN, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001919
arthurhungcc7f9802020-04-30 17:55:40 +08001920 // ACTION_MOVE (second slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001921 mDevice->sendMove(secondPoint + Point(1, 1));
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001922 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001923 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1924 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1925
arthurhungcc7f9802020-04-30 17:55:40 +08001926 // Send MT_TOOL_PALM (second slot), which indicates that the touch IC has determined this to be
1927 // a palm event.
1928 // Expect to receive the ACTION_POINTER_UP with cancel flag.
Arthur Hungaab25622020-01-16 11:22:11 +08001929 mDevice->sendToolType(MT_TOOL_PALM);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001930 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001931 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001932 ASSERT_EQ(ACTION_POINTER_1_UP, args.action);
arthurhungcc7f9802020-04-30 17:55:40 +08001933 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, args.flags);
Arthur Hungaab25622020-01-16 11:22:11 +08001934
arthurhungcc7f9802020-04-30 17:55:40 +08001935 // Send up to second slot, expect first slot send moving.
1936 mDevice->sendPointerUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001937 mDevice->sendSync();
arthurhungcc7f9802020-04-30 17:55:40 +08001938 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1939 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001940
arthurhungcc7f9802020-04-30 17:55:40 +08001941 // Send ACTION_UP (first slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001942 mDevice->sendSlot(FIRST_SLOT);
1943 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001944 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001945
arthurhungcc7f9802020-04-30 17:55:40 +08001946 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1947 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001948}
1949
Prabir Pradhanc09ec6d2023-08-14 22:31:43 +00001950/**
1951 * Some drivers historically have reported axis values outside of the range specified in the
1952 * evdev axis info. Ensure we don't crash when this happens. For example, a driver may report a
1953 * pressure value greater than the reported maximum, since it unclear what specific meaning the
1954 * maximum value for pressure has (beyond the maximum value that can be produced by a sensor),
1955 * and no units for pressure (resolution) is specified by the evdev documentation.
1956 */
1957TEST_P(TouchIntegrationTest, AcceptsAxisValuesOutsideReportedRange) {
1958 const Point centerPoint = mDevice->getCenterPoint();
1959
1960 // Down with pressure outside the reported range
1961 mDevice->sendSlot(FIRST_SLOT);
1962 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1963 mDevice->sendDown(centerPoint);
1964 mDevice->sendPressure(UinputTouchScreen::RAW_PRESSURE_MAX + 2);
1965 mDevice->sendSync();
1966 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1967 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
1968
1969 // Move to a point outside the reported range
1970 mDevice->sendMove(Point(DISPLAY_WIDTH, DISPLAY_HEIGHT) + Point(1, 1));
1971 mDevice->sendSync();
1972 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1973 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
1974
1975 // Up
1976 mDevice->sendUp();
1977 mDevice->sendSync();
1978 ASSERT_NO_FATAL_FAILURE(
1979 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
1980}
1981
Arpit Singh440bf652023-08-09 09:23:43 +00001982TEST_P(TouchIntegrationTest, NotifiesPolicyWhenStylusGestureStarted) {
Prabir Pradhanda20b172022-09-26 17:01:18 +00001983 const Point centerPoint = mDevice->getCenterPoint();
1984
1985 // Send down with the pen tool selected. The policy should be notified of the stylus presence.
1986 mDevice->sendSlot(FIRST_SLOT);
1987 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1988 mDevice->sendToolType(MT_TOOL_PEN);
1989 mDevice->sendDown(centerPoint);
1990 mDevice->sendSync();
1991 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1992 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001993 WithToolType(ToolType::STYLUS))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00001994
1995 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotified(mDeviceInfo.getId()));
1996
1997 // Release the stylus touch.
1998 mDevice->sendUp();
1999 mDevice->sendSync();
2000 ASSERT_NO_FATAL_FAILURE(
2001 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2002
2003 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotNotified());
2004
2005 // Touch down with the finger, without the pen tool selected. The policy is not notified.
2006 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2007 mDevice->sendToolType(MT_TOOL_FINGER);
2008 mDevice->sendDown(centerPoint);
2009 mDevice->sendSync();
2010 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2011 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002012 WithToolType(ToolType::FINGER))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00002013
2014 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotNotified());
2015
2016 mDevice->sendUp();
2017 mDevice->sendSync();
2018 ASSERT_NO_FATAL_FAILURE(
2019 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2020
2021 // Send a move event with the stylus tool without BTN_TOUCH to generate a hover enter.
2022 // The policy should be notified of the stylus presence.
2023 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2024 mDevice->sendToolType(MT_TOOL_PEN);
2025 mDevice->sendMove(centerPoint);
2026 mDevice->sendSync();
2027 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2028 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002029 WithToolType(ToolType::STYLUS))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00002030
2031 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotified(mDeviceInfo.getId()));
2032}
2033
Arpit Singh440bf652023-08-09 09:23:43 +00002034TEST_P(TouchIntegrationTest, ExternalStylusConnectedDuringTouchGesture) {
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002035 const Point centerPoint = mDevice->getCenterPoint();
2036
2037 // Down
2038 mDevice->sendSlot(FIRST_SLOT);
2039 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2040 mDevice->sendDown(centerPoint);
2041 mDevice->sendSync();
2042 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2043 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
2044
2045 // Move
2046 mDevice->sendMove(centerPoint + Point(1, 1));
2047 mDevice->sendSync();
2048 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2049 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
2050
2051 // Connecting an external stylus mid-gesture should not interrupt the ongoing gesture stream.
2052 auto externalStylus = createUinputDevice<UinputExternalStylus>();
2053 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002054 const auto stylusInfo = waitForDevice(externalStylus->getName());
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002055 ASSERT_TRUE(stylusInfo);
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002056
2057 // Move
2058 mDevice->sendMove(centerPoint + Point(2, 2));
2059 mDevice->sendSync();
2060 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2061 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
2062
2063 // Disconnecting an external stylus mid-gesture should not interrupt the ongoing gesture stream.
2064 externalStylus.reset();
2065 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002066 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2067
2068 // Up
2069 mDevice->sendUp();
2070 mDevice->sendSync();
2071 ASSERT_NO_FATAL_FAILURE(
2072 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2073
2074 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2075}
2076
Arpit Singh440bf652023-08-09 09:23:43 +00002077INSTANTIATE_TEST_SUITE_P(TouchIntegrationTestDisplayVariants, TouchIntegrationTest,
2078 testing::Values(TouchIntegrationTestDisplays::DISPLAY_INTERNAL,
2079 TouchIntegrationTestDisplays::DISPLAY_INPUT_PORT,
2080 TouchIntegrationTestDisplays::DISPLAY_UNIQUE_ID));
2081
Prabir Pradhan124ea442022-10-28 20:27:44 +00002082// --- StylusButtonIntegrationTest ---
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002083
Prabir Pradhan124ea442022-10-28 20:27:44 +00002084// Verify the behavior of button presses reported by various kinds of styluses, including buttons
2085// reported by the touchscreen's device, by a fused external stylus, and by an un-fused external
2086// stylus.
2087template <typename UinputStylusDevice>
Arpit Singh440bf652023-08-09 09:23:43 +00002088class StylusButtonIntegrationTest : public BaseTouchIntegrationTest {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002089protected:
2090 void SetUp() override {
2091#if !defined(__ANDROID__)
2092 GTEST_SKIP();
2093#endif
Arpit Singh440bf652023-08-09 09:23:43 +00002094 BaseTouchIntegrationTest::SetUp();
Prabir Pradhan124ea442022-10-28 20:27:44 +00002095 mTouchscreen = mDevice.get();
2096 mTouchscreenInfo = mDeviceInfo;
2097
2098 setUpStylusDevice();
2099 }
2100
2101 UinputStylusDevice* mStylus{nullptr};
2102 InputDeviceInfo mStylusInfo{};
2103
2104 UinputTouchScreen* mTouchscreen{nullptr};
2105 InputDeviceInfo mTouchscreenInfo{};
2106
2107private:
2108 // When we are attempting to test stylus button events that are sent from the touchscreen,
2109 // use the same Uinput device for the touchscreen and the stylus.
2110 template <typename T = UinputStylusDevice>
2111 std::enable_if_t<std::is_same_v<UinputTouchScreen, T>, void> setUpStylusDevice() {
2112 mStylus = mDevice.get();
2113 mStylusInfo = mDeviceInfo;
2114 }
2115
2116 // When we are attempting to stylus buttons from an external stylus being merged with touches
2117 // from a touchscreen, create a new Uinput device through which stylus buttons can be injected.
2118 template <typename T = UinputStylusDevice>
2119 std::enable_if_t<!std::is_same_v<UinputTouchScreen, T>, void> setUpStylusDevice() {
2120 mStylusDeviceLifecycleTracker = createUinputDevice<T>();
2121 mStylus = mStylusDeviceLifecycleTracker.get();
2122 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002123 const auto info = waitForDevice(mStylus->getName());
Prabir Pradhan124ea442022-10-28 20:27:44 +00002124 ASSERT_TRUE(info);
2125 mStylusInfo = *info;
2126 }
2127
2128 std::unique_ptr<UinputStylusDevice> mStylusDeviceLifecycleTracker{};
2129
2130 // Hide the base class's device to expose it with a different name for readability.
Arpit Singh440bf652023-08-09 09:23:43 +00002131 using BaseTouchIntegrationTest::mDevice;
2132 using BaseTouchIntegrationTest::mDeviceInfo;
Prabir Pradhan124ea442022-10-28 20:27:44 +00002133};
2134
2135using StylusButtonIntegrationTestTypes =
2136 ::testing::Types<UinputTouchScreen, UinputExternalStylus, UinputExternalStylusWithPressure>;
2137TYPED_TEST_SUITE(StylusButtonIntegrationTest, StylusButtonIntegrationTestTypes);
2138
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002139TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsGenerateKeyEvents) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002140 const auto stylusId = TestFixture::mStylusInfo.getId();
2141
2142 TestFixture::mStylus->pressKey(BTN_STYLUS);
2143 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2144 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2145 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2146
2147 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2148 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002149 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002150 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002151}
2152
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002153TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingTouchGesture) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002154 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2155 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2156 const auto stylusId = TestFixture::mStylusInfo.getId();
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002157
2158 // Press the stylus button.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002159 TestFixture::mStylus->pressKey(BTN_STYLUS);
2160 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002161 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002162 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002163
2164 // Start and finish a stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002165 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2166 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2167 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2168 TestFixture::mTouchscreen->sendDown(centerPoint);
2169 TestFixture::mTouchscreen->sendSync();
2170 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002171 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002172 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002173 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2174 WithDeviceId(touchscreenId))));
2175 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002176 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002177 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002178 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2179 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002180
Prabir Pradhan124ea442022-10-28 20:27:44 +00002181 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2182 TestFixture::mTouchscreen->sendSync();
2183 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002184 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002185 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002186 WithDeviceId(touchscreenId))));
2187 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002188 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002189 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002190 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002191
2192 // Release the stylus button.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002193 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2194 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002195 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002196 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002197}
2198
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002199TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingHoveringTouchGesture) {
Prabir Pradhan9a561c22022-11-07 16:11:23 +00002200 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2201 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2202 const auto stylusId = TestFixture::mStylusInfo.getId();
2203 auto toolTypeDevice =
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002204 AllOf(WithToolType(ToolType::STYLUS), WithDeviceId(touchscreenId));
Prabir Pradhan9a561c22022-11-07 16:11:23 +00002205
2206 // Press the stylus button.
2207 TestFixture::mStylus->pressKey(BTN_STYLUS);
2208 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2209 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2210 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2211
2212 // Start hovering with the stylus.
2213 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2214 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2215 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2216 TestFixture::mTouchscreen->sendMove(centerPoint);
2217 TestFixture::mTouchscreen->sendSync();
2218 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2219 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2220 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2221 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2222 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2223 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2224 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2225 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
2226 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2227
2228 // Touch down with the stylus.
2229 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2230 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2231 TestFixture::mTouchscreen->sendDown(centerPoint);
2232 TestFixture::mTouchscreen->sendSync();
2233 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2234 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
2235 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2236
2237 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2238 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
2239 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2240
2241 // Stop touching with the stylus, and start hovering.
2242 TestFixture::mTouchscreen->sendUp();
2243 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2244 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2245 TestFixture::mTouchscreen->sendMove(centerPoint);
2246 TestFixture::mTouchscreen->sendSync();
2247 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2248 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_UP),
2249 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2250 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2251 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2252 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2253 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2254 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2255 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2256
2257 // Stop hovering.
2258 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2259 TestFixture::mTouchscreen->sendSync();
2260 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2261 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
2262 WithButtonState(0))));
2263 // TODO(b/257971675): Fix inconsistent button state when exiting hover.
2264 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2265 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
2266 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2267
2268 // Release the stylus button.
2269 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2270 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2271 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
2272 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2273}
2274
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002275TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsWithinTouchGesture) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002276 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2277 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2278 const auto stylusId = TestFixture::mStylusInfo.getId();
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002279
2280 // Start a stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002281 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2282 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2283 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2284 TestFixture::mTouchscreen->sendDown(centerPoint);
2285 TestFixture::mTouchscreen->sendSync();
2286 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002287 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002288 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002289 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002290
2291 // Press and release a stylus button. Each change in button state also generates a MOVE event.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002292 TestFixture::mStylus->pressKey(BTN_STYLUS);
2293 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002294 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002295 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2296 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002297 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002298 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002299 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2300 WithDeviceId(touchscreenId))));
2301 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002302 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002303 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002304 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2305 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002306
Prabir Pradhan124ea442022-10-28 20:27:44 +00002307 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2308 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002309 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002310 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2311 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002312 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002313 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002314 WithDeviceId(touchscreenId))));
2315 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002316 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002317 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002318 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002319
2320 // Finish the stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002321 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2322 TestFixture::mTouchscreen->sendSync();
2323 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002324 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002325 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002326 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002327}
2328
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002329TYPED_TEST(StylusButtonIntegrationTest, StylusButtonMotionEventsDisabled) {
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002330 TestFixture::mFakePolicy->setStylusButtonMotionEventsEnabled(false);
2331 TestFixture::mReader->requestRefreshConfiguration(
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002332 InputReaderConfiguration::Change::STYLUS_BUTTON_REPORTING);
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002333
2334 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2335 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2336 const auto stylusId = TestFixture::mStylusInfo.getId();
2337
2338 // Start a stylus gesture. By the time this event is processed, the configuration change that
2339 // was requested is guaranteed to be completed.
2340 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2341 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2342 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2343 TestFixture::mTouchscreen->sendDown(centerPoint);
2344 TestFixture::mTouchscreen->sendSync();
2345 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2346 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002347 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002348 WithDeviceId(touchscreenId))));
2349
2350 // Press and release a stylus button. Each change only generates a MOVE motion event.
2351 // Key events are unaffected.
2352 TestFixture::mStylus->pressKey(BTN_STYLUS);
2353 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2354 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2355 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2356 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2357 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002358 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002359 WithDeviceId(touchscreenId))));
2360
2361 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2362 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2363 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
2364 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2365 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2366 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002367 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002368 WithDeviceId(touchscreenId))));
2369
2370 // Finish the stylus gesture.
2371 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2372 TestFixture::mTouchscreen->sendSync();
2373 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2374 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002375 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002376 WithDeviceId(touchscreenId))));
2377}
2378
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002379// --- ExternalStylusIntegrationTest ---
2380
2381// Verify the behavior of an external stylus. An external stylus can report pressure or button
2382// data independently of the touchscreen, which is then sent as a MotionEvent as part of an
2383// ongoing stylus gesture that is being emitted by the touchscreen.
Arpit Singh440bf652023-08-09 09:23:43 +00002384using ExternalStylusIntegrationTest = BaseTouchIntegrationTest;
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002385
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002386TEST_F(ExternalStylusIntegrationTest, ExternalStylusConnectionChangesTouchscreenSource) {
2387 // Create an external stylus capable of reporting pressure data that
2388 // should be fused with a touch pointer.
2389 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2390 createUinputDevice<UinputExternalStylusWithPressure>();
2391 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002392 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002393 ASSERT_TRUE(stylusInfo);
2394
2395 // Connecting an external stylus changes the source of the touchscreen.
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002396 const auto deviceInfo = waitForDevice(mDevice->getName());
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002397 ASSERT_TRUE(deviceInfo);
2398 ASSERT_TRUE(isFromSource(deviceInfo->getSources(), STYLUS_FUSION_SOURCE));
2399}
2400
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002401TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureReported) {
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002402 const Point centerPoint = mDevice->getCenterPoint();
2403
2404 // Create an external stylus capable of reporting pressure data that
2405 // should be fused with a touch pointer.
2406 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2407 createUinputDevice<UinputExternalStylusWithPressure>();
2408 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002409 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002410 ASSERT_TRUE(stylusInfo);
2411
2412 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2413
2414 const auto touchscreenId = mDeviceInfo.getId();
2415
2416 // Set a pressure value on the stylus. It doesn't generate any events.
2417 const auto& RAW_PRESSURE_MAX = UinputExternalStylusWithPressure::RAW_PRESSURE_MAX;
2418 stylus->setPressure(100);
2419 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2420
2421 // Start a finger gesture, and ensure it shows up as stylus gesture
2422 // with the pressure set by the external stylus.
Dominik Laskowski2f01d772022-03-23 16:01:29 -07002423 mDevice->sendSlot(FIRST_SLOT);
Chris Ye1b0c7342020-07-28 21:57:03 -07002424 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002425 mDevice->sendToolType(MT_TOOL_FINGER);
Prabir Pradhanb54ffb22022-10-27 18:03:34 +00002426 mDevice->sendDown(centerPoint);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002427 mDevice->sendSync();
2428 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002429 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithToolType(ToolType::STYLUS),
2430 WithButtonState(0), WithSource(STYLUS_FUSION_SOURCE), WithDeviceId(touchscreenId),
2431 WithPressure(100.f / RAW_PRESSURE_MAX))));
Dominik Laskowski2f01d772022-03-23 16:01:29 -07002432
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002433 // Change the pressure on the external stylus, and ensure the touchscreen generates a MOVE
2434 // event with the updated pressure.
2435 stylus->setPressure(200);
Vaibhav Devmuraridd82b8e2022-08-16 15:34:01 +00002436 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002437 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithToolType(ToolType::STYLUS),
2438 WithButtonState(0), WithSource(STYLUS_FUSION_SOURCE), WithDeviceId(touchscreenId),
2439 WithPressure(200.f / RAW_PRESSURE_MAX))));
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002440
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002441 // The external stylus did not generate any events.
2442 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2443 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
2444}
2445
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002446TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureNotReported) {
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002447 const Point centerPoint = mDevice->getCenterPoint();
2448
2449 // Create an external stylus capable of reporting pressure data that
2450 // should be fused with a touch pointer.
2451 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2452 createUinputDevice<UinputExternalStylusWithPressure>();
2453 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002454 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002455 ASSERT_TRUE(stylusInfo);
2456
2457 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2458
2459 const auto touchscreenId = mDeviceInfo.getId();
2460
2461 // Set a pressure value of 0 on the stylus. It doesn't generate any events.
2462 const auto& RAW_PRESSURE_MAX = UinputExternalStylusWithPressure::RAW_PRESSURE_MAX;
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002463 // Send a non-zero value first to prevent the kernel from consuming the zero event.
2464 stylus->setPressure(100);
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002465 stylus->setPressure(0);
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002466 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002467
2468 // Start a finger gesture. The touch device will withhold generating any touches for
2469 // up to 72 milliseconds while waiting for pressure data from the external stylus.
2470 mDevice->sendSlot(FIRST_SLOT);
2471 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2472 mDevice->sendToolType(MT_TOOL_FINGER);
2473 mDevice->sendDown(centerPoint);
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002474 const auto syncTime = std::chrono::system_clock::now();
2475 // After 72 ms, the event *will* be generated. If we wait the full 72 ms to check that NO event
2476 // is generated in that period, there will be a race condition between the event being generated
2477 // and the test's wait timeout expiring. Thus, we wait for a shorter duration in the test, which
2478 // will reduce the liklihood of the race condition occurring.
2479 const auto waitUntilTimeForNoEvent =
2480 syncTime + std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT / 2));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07002481 mDevice->sendSync();
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002482 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled(waitUntilTimeForNoEvent));
Michael Wrightd02c5b62014-02-10 15:10:22 -08002483
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002484 // Since the external stylus did not report a pressure value within the timeout,
2485 // it shows up as a finger pointer.
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002486 const auto waitUntilTimeForEvent = syncTime +
2487 std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT)) + EVENT_HAPPENED_TIMEOUT;
2488 ASSERT_NO_FATAL_FAILURE(
2489 mTestListener->assertNotifyMotionWasCalled(AllOf(WithMotionAction(
2490 AMOTION_EVENT_ACTION_DOWN),
2491 WithSource(AINPUT_SOURCE_TOUCHSCREEN |
2492 AINPUT_SOURCE_STYLUS),
2493 WithToolType(ToolType::FINGER),
2494 WithDeviceId(touchscreenId),
2495 WithPressure(1.f)),
2496 waitUntilTimeForEvent));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002497
2498 // Change the pressure on the external stylus. Since the pressure was not present at the start
2499 // of the gesture, it is ignored for now.
2500 stylus->setPressure(200);
2501 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2502
2503 // Finish the finger gesture.
Michael Wrightd02c5b62014-02-10 15:10:22 -08002504 mDevice->sendTrackingId(INVALID_TRACKING_ID);
2505 mDevice->sendSync();
2506 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2507 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002508 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002509 WithToolType(ToolType::FINGER))));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002510
2511 // Start a new gesture. Since we have a valid pressure value, it shows up as a stylus.
2512 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2513 mDevice->sendToolType(MT_TOOL_FINGER);
2514 mDevice->sendDown(centerPoint);
2515 mDevice->sendSync();
2516 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002517 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithSource(STYLUS_FUSION_SOURCE),
2518 WithToolType(ToolType::STYLUS), WithButtonState(0), WithDeviceId(touchscreenId),
2519 WithPressure(200.f / RAW_PRESSURE_MAX))));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002520
2521 // The external stylus did not generate any events.
2522 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2523 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002524}
Siarhei Vishniakou1983a712021-06-04 19:27:09 +00002525
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002526TEST_F(ExternalStylusIntegrationTest, UnfusedExternalStylus) {
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002527 const Point centerPoint = mDevice->getCenterPoint();
2528
2529 // Create an external stylus device that does not support pressure. It should not affect any
2530 // touch pointers.
2531 std::unique_ptr<UinputExternalStylus> stylus = createUinputDevice<UinputExternalStylus>();
2532 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002533 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002534 ASSERT_TRUE(stylusInfo);
2535
2536 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2537
2538 const auto touchscreenId = mDeviceInfo.getId();
2539
2540 // Start a finger gesture and ensure a finger pointer is generated for it, without waiting for
2541 // pressure data from the external stylus.
2542 mDevice->sendSlot(FIRST_SLOT);
2543 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2544 mDevice->sendToolType(MT_TOOL_FINGER);
2545 mDevice->sendDown(centerPoint);
2546 auto waitUntil = std::chrono::system_clock::now() +
2547 std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT));
2548 mDevice->sendSync();
2549 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002550 mTestListener->assertNotifyMotionWasCalled(AllOf(WithMotionAction(
2551 AMOTION_EVENT_ACTION_DOWN),
2552 WithToolType(ToolType::FINGER),
2553 WithSource(AINPUT_SOURCE_TOUCHSCREEN |
2554 AINPUT_SOURCE_STYLUS),
2555 WithButtonState(0),
2556 WithDeviceId(touchscreenId),
2557 WithPressure(1.f)),
2558 waitUntil));
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002559
2560 // The external stylus did not generate any events.
2561 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2562 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
2563}
2564
Michael Wrightd02c5b62014-02-10 15:10:22 -08002565// --- InputDeviceTest ---
2566class InputDeviceTest : public testing::Test {
2567protected:
2568 static const char* DEVICE_NAME;
2569 static const char* DEVICE_LOCATION;
2570 static const int32_t DEVICE_ID;
2571 static const int32_t DEVICE_GENERATION;
2572 static const int32_t DEVICE_CONTROLLER_NUMBER;
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002573 static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002574 static const int32_t EVENTHUB_ID;
2575 static const std::string DEVICE_BLUETOOTH_ADDRESS;
2576
2577 std::shared_ptr<FakeEventHub> mFakeEventHub;
2578 sp<FakeInputReaderPolicy> mFakePolicy;
2579 std::unique_ptr<TestInputListener> mFakeListener;
2580 std::unique_ptr<InstrumentedInputReader> mReader;
2581 std::shared_ptr<InputDevice> mDevice;
2582
2583 void SetUp() override {
2584 mFakeEventHub = std::make_unique<FakeEventHub>();
2585 mFakePolicy = sp<FakeInputReaderPolicy>::make();
2586 mFakeListener = std::make_unique<TestInputListener>();
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002587 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Michael Wrightd02c5b62014-02-10 15:10:22 -08002588 *mFakeListener);
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002589 InputDeviceIdentifier identifier;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002590 identifier.name = DEVICE_NAME;
2591 identifier.location = DEVICE_LOCATION;
2592 identifier.bluetoothAddress = DEVICE_BLUETOOTH_ADDRESS;
2593 mDevice = std::make_shared<InputDevice>(mReader->getContext(), DEVICE_ID, DEVICE_GENERATION,
2594 identifier);
2595 mReader->pushNextDevice(mDevice);
2596 mFakeEventHub->addDevice(EVENTHUB_ID, DEVICE_NAME, ftl::Flags<InputDeviceClass>(0));
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002597 mReader->loopOnce();
Michael Wrightd02c5b62014-02-10 15:10:22 -08002598 }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002599
2600 void TearDown() override {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002601 mFakeListener.reset();
2602 mFakePolicy.clear();
2603 }
2604};
2605
2606const char* InputDeviceTest::DEVICE_NAME = "device";
2607const char* InputDeviceTest::DEVICE_LOCATION = "USB1";
2608const int32_t InputDeviceTest::DEVICE_ID = END_RESERVED_ID + 1000;
2609const int32_t InputDeviceTest::DEVICE_GENERATION = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002610const int32_t InputDeviceTest::DEVICE_CONTROLLER_NUMBER = 0;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002611const ftl::Flags<InputDeviceClass> InputDeviceTest::DEVICE_CLASSES =
2612 InputDeviceClass::KEYBOARD | InputDeviceClass::TOUCH | InputDeviceClass::JOYSTICK;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002613const int32_t InputDeviceTest::EVENTHUB_ID = 1;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002614const std::string InputDeviceTest::DEVICE_BLUETOOTH_ADDRESS = "11:AA:22:BB:33:CC";
2615
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002616TEST_F(InputDeviceTest, ImmutableProperties) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002617 ASSERT_EQ(DEVICE_ID, mDevice->getId());
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002618 ASSERT_STREQ(DEVICE_NAME, mDevice->getName().c_str());
2619 ASSERT_EQ(ftl::Flags<InputDeviceClass>(0), mDevice->getClasses());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002620}
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002621
Michael Wrightd02c5b62014-02-10 15:10:22 -08002622TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsFalse) {
2623 ASSERT_EQ(mDevice->isEnabled(), false);
2624}
2625
2626TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
2627 // Configuration.
2628 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002629 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002630
2631 // Reset.
2632 unused += mDevice->reset(ARBITRARY_TIME);
2633
2634 NotifyDeviceResetArgs resetArgs;
2635 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
2636 ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
2637 ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
2638
2639 // Metadata.
2640 ASSERT_TRUE(mDevice->isIgnored());
2641 ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mDevice->getSources());
2642
2643 InputDeviceInfo info = mDevice->getDeviceInfo();
2644 ASSERT_EQ(DEVICE_ID, info.getId());
2645 ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.c_str());
2646 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NONE, info.getKeyboardType());
2647 ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, info.getSources());
2648
2649 // State queries.
2650 ASSERT_EQ(0, mDevice->getMetaState());
2651
2652 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, 0))
2653 << "Ignored device should return unknown key code state.";
2654 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 0))
2655 << "Ignored device should return unknown scan code state.";
2656 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 0))
2657 << "Ignored device should return unknown switch state.";
2658
2659 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B};
2660 uint8_t flags[2] = { 0, 1 };
2661 ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, keyCodes, flags))
2662 << "Ignored device should never mark any key codes.";
2663 ASSERT_EQ(0, flags[0]) << "Flag for unsupported key should be unchanged.";
2664 ASSERT_EQ(1, flags[1]) << "Flag for unsupported key should be unchanged.";
2665}
2666
2667TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRequestsToMappers) {
2668 // Configuration.
2669 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "key", "value");
2670
2671 FakeInputMapper& mapper1 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00002672 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2673 AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002674 mapper1.setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC);
2675 mapper1.setMetaState(AMETA_ALT_ON);
2676 mapper1.addSupportedKeyCode(AKEYCODE_A);
2677 mapper1.addSupportedKeyCode(AKEYCODE_B);
2678 mapper1.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
2679 mapper1.setKeyCodeState(AKEYCODE_B, AKEY_STATE_UP);
2680 mapper1.setScanCodeState(2, AKEY_STATE_DOWN);
2681 mapper1.setScanCodeState(3, AKEY_STATE_UP);
2682 mapper1.setSwitchState(4, AKEY_STATE_DOWN);
2683
2684 FakeInputMapper& mapper2 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00002685 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2686 AINPUT_SOURCE_TOUCHSCREEN);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002687 mapper2.setMetaState(AMETA_SHIFT_ON);
2688
2689 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002690 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002691
Harry Cuttsf13161a2023-03-08 14:15:49 +00002692 std::optional<std::string> propertyValue = mDevice->getConfiguration().getString("key");
2693 ASSERT_TRUE(propertyValue.has_value())
Michael Wrightd02c5b62014-02-10 15:10:22 -08002694 << "Device should have read configuration during configuration phase.";
Harry Cuttsf13161a2023-03-08 14:15:49 +00002695 ASSERT_EQ("value", *propertyValue);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002696
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002697 ASSERT_NO_FATAL_FAILURE(mapper1.assertConfigureWasCalled());
2698 ASSERT_NO_FATAL_FAILURE(mapper2.assertConfigureWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002699
2700 // Reset
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002701 unused += mDevice->reset(ARBITRARY_TIME);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002702 ASSERT_NO_FATAL_FAILURE(mapper1.assertResetWasCalled());
2703 ASSERT_NO_FATAL_FAILURE(mapper2.assertResetWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002704
2705 NotifyDeviceResetArgs resetArgs;
2706 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
2707 ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
2708 ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
2709
2710 // Metadata.
2711 ASSERT_FALSE(mDevice->isIgnored());
2712 ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), mDevice->getSources());
2713
Siarhei Vishniakou1983a712021-06-04 19:27:09 +00002714 InputDeviceInfo info = mDevice->getDeviceInfo();
Michael Wrightd02c5b62014-02-10 15:10:22 -08002715 ASSERT_EQ(DEVICE_ID, info.getId());
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002716 ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002717 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, info.getKeyboardType());
2718 ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), info.getSources());
2719
2720 // State queries.
2721 ASSERT_EQ(AMETA_ALT_ON | AMETA_SHIFT_ON, mDevice->getMetaState())
2722 << "Should query mappers and combine meta states.";
2723
2724 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2725 << "Should return unknown key code state when source not supported.";
2726 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2727 << "Should return unknown scan code state when source not supported.";
2728 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2729 << "Should return unknown switch state when source not supported.";
2730
2731 ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, AKEYCODE_A))
2732 << "Should query mapper when source is supported.";
2733 ASSERT_EQ(AKEY_STATE_UP, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 3))
2734 << "Should query mapper when source is supported.";
2735 ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 4))
2736 << "Should query mapper when source is supported.";
2737
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002738 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2};
Michael Wrightd02c5b62014-02-10 15:10:22 -08002739 uint8_t flags[4] = { 0, 0, 0, 1 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002740 ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -08002741 << "Should do nothing when source is unsupported.";
2742 ASSERT_EQ(0, flags[0]) << "Flag should be unchanged when source is unsupported.";
2743 ASSERT_EQ(0, flags[1]) << "Flag should be unchanged when source is unsupported.";
2744 ASSERT_EQ(0, flags[2]) << "Flag should be unchanged when source is unsupported.";
2745 ASSERT_EQ(1, flags[3]) << "Flag should be unchanged when source is unsupported.";
2746
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002747 ASSERT_TRUE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -08002748 << "Should query mapper when source is supported.";
2749 ASSERT_EQ(1, flags[0]) << "Flag for supported key should be set.";
2750 ASSERT_EQ(1, flags[1]) << "Flag for supported key should be set.";
2751 ASSERT_EQ(0, flags[2]) << "Flag for unsupported key should be unchanged.";
2752 ASSERT_EQ(1, flags[3]) << "Flag for unsupported key should be unchanged.";
2753
2754 // Event handling.
2755 RawEvent event;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002756 event.deviceId = EVENTHUB_ID;
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002757 unused += mDevice->process(&event, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002758
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002759 ASSERT_NO_FATAL_FAILURE(mapper1.assertProcessWasCalled());
2760 ASSERT_NO_FATAL_FAILURE(mapper2.assertProcessWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002761}
2762
Yeabkal Wubshitb1b96db2024-01-24 12:47:00 -08002763TEST_F(InputDeviceTest, Configure_SmoothScrollViewBehaviorNotSet) {
2764 // Set some behavior to force the configuration to be update.
2765 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "1");
2766 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2767 AINPUT_SOURCE_KEYBOARD);
2768
2769 std::list<NotifyArgs> unused =
2770 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2771 /*changes=*/{});
2772
2773 ASSERT_FALSE(mDevice->getDeviceInfo().getViewBehavior().shouldSmoothScroll.has_value());
2774}
2775
2776TEST_F(InputDeviceTest, Configure_SmoothScrollViewBehaviorEnabled) {
2777 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.viewBehavior_smoothScroll", "1");
2778 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2779 AINPUT_SOURCE_KEYBOARD);
2780
2781 std::list<NotifyArgs> unused =
2782 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2783 /*changes=*/{});
2784
2785 ASSERT_TRUE(mDevice->getDeviceInfo().getViewBehavior().shouldSmoothScroll.value_or(false));
2786}
2787
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -07002788TEST_F(InputDeviceTest, WakeDevice_AddsWakeFlagToProcessNotifyArgs) {
2789 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "1");
2790 FakeInputMapper& mapper =
2791 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2792 AINPUT_SOURCE_KEYBOARD);
2793 NotifyMotionArgs args1;
2794 NotifySwitchArgs args2;
2795 NotifyKeyArgs args3;
2796 mapper.setProcessResult({args1, args2, args3});
2797
2798 InputReaderConfiguration config;
2799 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2800
2801 RawEvent event;
2802 event.deviceId = EVENTHUB_ID;
2803 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2804
2805 for (auto& arg : notifyArgs) {
2806 if (const auto notifyMotionArgs = std::get_if<NotifyMotionArgs>(&arg)) {
2807 ASSERT_EQ(POLICY_FLAG_WAKE, notifyMotionArgs->policyFlags);
2808 } else if (const auto notifySwitchArgs = std::get_if<NotifySwitchArgs>(&arg)) {
2809 ASSERT_EQ(POLICY_FLAG_WAKE, notifySwitchArgs->policyFlags);
2810 } else if (const auto notifyKeyArgs = std::get_if<NotifyKeyArgs>(&arg)) {
2811 ASSERT_EQ(POLICY_FLAG_WAKE, notifyKeyArgs->policyFlags);
2812 }
2813 }
2814}
2815
2816TEST_F(InputDeviceTest, NotWakeDevice_DoesNotAddWakeFlagToProcessNotifyArgs) {
2817 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "0");
2818 FakeInputMapper& mapper =
2819 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2820 AINPUT_SOURCE_KEYBOARD);
2821 NotifyMotionArgs args;
2822 mapper.setProcessResult({args});
2823
2824 InputReaderConfiguration config;
2825 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2826
2827 RawEvent event;
2828 event.deviceId = EVENTHUB_ID;
2829 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2830
2831 // POLICY_FLAG_WAKE is not added to the NotifyArgs.
2832 ASSERT_EQ(0u, std::get<NotifyMotionArgs>(notifyArgs.front()).policyFlags);
2833}
2834
2835TEST_F(InputDeviceTest, NotWakeDevice_DoesNotRemoveExistingWakeFlagFromProcessNotifyArgs) {
2836 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "0");
2837 FakeInputMapper& mapper =
2838 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2839 AINPUT_SOURCE_KEYBOARD);
2840 NotifyMotionArgs args;
2841 args.policyFlags = POLICY_FLAG_WAKE;
2842 mapper.setProcessResult({args});
2843
2844 InputReaderConfiguration config;
2845 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2846
2847 RawEvent event;
2848 event.deviceId = EVENTHUB_ID;
2849 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2850
2851 // The POLICY_FLAG_WAKE is preserved, despite the device being a non-wake device.
2852 ASSERT_EQ(POLICY_FLAG_WAKE, std::get<NotifyMotionArgs>(notifyArgs.front()).policyFlags);
2853}
2854
Arthur Hung2c9a3342019-07-23 14:18:59 +08002855// A single input device is associated with a specific display. Check that:
2856// 1. Device is disabled if the viewport corresponding to the associated display is not found
Arpit Singh48189772023-05-30 14:12:49 +00002857// 2. Device is disabled when configure API is called
Arthur Hung2c9a3342019-07-23 14:18:59 +08002858TEST_F(InputDeviceTest, Configure_AssignsDisplayPort) {
Arpit Singh8e6fb252023-04-06 11:49:17 +00002859 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2860 AINPUT_SOURCE_TOUCHSCREEN);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002861
2862 // First Configuration.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002863 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002864 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2865 /*changes=*/{});
Arthur Hung2c9a3342019-07-23 14:18:59 +08002866
2867 // Device should be enabled by default.
2868 ASSERT_TRUE(mDevice->isEnabled());
2869
2870 // Prepare associated info.
2871 constexpr uint8_t hdmi = 1;
2872 const std::string UNIQUE_ID = "local:1";
2873
2874 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002875 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002876 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002877 // Device should be disabled because it is associated with a specific display via
2878 // input port <-> display port association, but the corresponding display is not found
2879 ASSERT_FALSE(mDevice->isEnabled());
2880
2881 // Prepare displays.
2882 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +00002883 ui::ROTATION_0, /*isActive=*/true, UNIQUE_ID, hdmi,
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00002884 ViewportType::INTERNAL);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002885 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002886 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002887 ASSERT_TRUE(mDevice->isEnabled());
2888
2889 // Device should be disabled after set disable.
2890 mFakePolicy->addDisabledDevice(mDevice->getId());
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002891 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002892 InputReaderConfiguration::Change::ENABLED_STATE);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002893 ASSERT_FALSE(mDevice->isEnabled());
2894
2895 // Device should still be disabled even found the associated display.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002896 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002897 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002898 ASSERT_FALSE(mDevice->isEnabled());
2899}
Michael Wrightd02c5b62014-02-10 15:10:22 -08002900
Christine Franks1ba71cc2021-04-07 14:37:42 -07002901TEST_F(InputDeviceTest, Configure_AssignsDisplayUniqueId) {
2902 // Device should be enabled by default.
2903 mFakePolicy->clearViewports();
Arpit Singh8e6fb252023-04-06 11:49:17 +00002904 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2905 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002906 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002907 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2908 /*changes=*/{});
Christine Franks1ba71cc2021-04-07 14:37:42 -07002909 ASSERT_TRUE(mDevice->isEnabled());
2910
2911 // Device should be disabled because it is associated with a specific display, but the
2912 // corresponding display is not found.
Christine Franks2a2293c2022-01-18 11:51:16 -08002913 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
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::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002916 ASSERT_FALSE(mDevice->isEnabled());
2917
2918 // Device should be enabled when a display is found.
2919 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00002920 ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
Christine Franks1ba71cc2021-04-07 14:37:42 -07002921 NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002922 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002923 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002924 ASSERT_TRUE(mDevice->isEnabled());
2925
2926 // Device should be disabled after set disable.
2927 mFakePolicy->addDisabledDevice(mDevice->getId());
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002928 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002929 InputReaderConfiguration::Change::ENABLED_STATE);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002930 ASSERT_FALSE(mDevice->isEnabled());
2931
2932 // Device should still be disabled even found the associated display.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002933 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002934 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002935 ASSERT_FALSE(mDevice->isEnabled());
2936}
2937
Christine Franks2a2293c2022-01-18 11:51:16 -08002938TEST_F(InputDeviceTest, Configure_UniqueId_CorrectlyMatches) {
2939 mFakePolicy->clearViewports();
Arpit Singh8e6fb252023-04-06 11:49:17 +00002940 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2941 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002942 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002943 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2944 /*changes=*/{});
Christine Franks2a2293c2022-01-18 11:51:16 -08002945
Christine Franks2a2293c2022-01-18 11:51:16 -08002946 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
2947 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00002948 ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
Christine Franks2a2293c2022-01-18 11:51:16 -08002949 NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan55c5ee22024-02-14 06:03:02 +00002950 const auto initialGeneration = mDevice->getGeneration();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002951 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002952 InputReaderConfiguration::Change::DISPLAY_INFO);
Antonio Kantek0ac5e092024-04-22 17:10:27 +00002953 ASSERT_EQ(DISPLAY_UNIQUE_ID, mDevice->getAssociatedDisplayUniqueIdByPort());
Prabir Pradhan55c5ee22024-02-14 06:03:02 +00002954 ASSERT_GT(mDevice->getGeneration(), initialGeneration);
2955 ASSERT_EQ(mDevice->getDeviceInfo().getAssociatedDisplayId(), SECONDARY_DISPLAY_ID);
Christine Franks2a2293c2022-01-18 11:51:16 -08002956}
2957
Siarhei Vishniakou30feb8c2022-09-28 10:48:29 -07002958/**
2959 * This test reproduces a crash caused by a dangling reference that remains after device is added
2960 * and removed. The reference is accessed in InputDevice::dump(..);
2961 */
2962TEST_F(InputDeviceTest, DumpDoesNotCrash) {
2963 constexpr int32_t TEST_EVENTHUB_ID = 10;
2964 mFakeEventHub->addDevice(TEST_EVENTHUB_ID, "Test EventHub device", InputDeviceClass::BATTERY);
2965
Harry Cutts33476232023-01-30 19:57:29 +00002966 InputDevice device(mReader->getContext(), /*id=*/1, /*generation=*/2, /*identifier=*/{});
Arpit Singh82f29a12023-06-13 15:05:53 +00002967 auto _ = device.addEventHubDevice(ARBITRARY_TIME, TEST_EVENTHUB_ID,
2968 mFakePolicy->getReaderConfiguration());
Siarhei Vishniakou30feb8c2022-09-28 10:48:29 -07002969 device.removeEventHubDevice(TEST_EVENTHUB_ID);
2970 std::string dumpStr, eventHubDevStr;
2971 device.dump(dumpStr, eventHubDevStr);
2972}
2973
Prabir Pradhanb54ffb22022-10-27 18:03:34 +00002974TEST_F(InputDeviceTest, GetBluetoothAddress) {
2975 const auto& address = mReader->getBluetoothAddress(DEVICE_ID);
2976 ASSERT_TRUE(address);
2977 ASSERT_EQ(DEVICE_BLUETOOTH_ADDRESS, *address);
2978}
2979
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002980TEST_F(InputDeviceTest, KernelBufferOverflowResetsMappers) {
2981 mFakePolicy->clearViewports();
2982 FakeInputMapper& mapper =
2983 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2984 AINPUT_SOURCE_KEYBOARD);
2985 std::list<NotifyArgs> unused =
2986 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2987 /*changes=*/{});
2988
2989 mapper.assertConfigureWasCalled();
2990 mapper.assertResetWasNotCalled();
2991
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -08002992 RawEvent event{.when = ARBITRARY_TIME,
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002993 .readTime = ARBITRARY_TIME,
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -08002994 .deviceId = EVENTHUB_ID,
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002995 .type = EV_SYN,
2996 .code = SYN_REPORT,
2997 .value = 0};
2998
2999 // Events are processed normally.
3000 unused = mDevice->process(&event, /*count=*/1);
3001 mapper.assertProcessWasCalled();
3002
3003 // Simulate a kernel buffer overflow, which generates a SYN_DROPPED event.
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003004 event.type = EV_SYN;
3005 event.code = SYN_DROPPED;
3006 event.value = 0;
3007 unused = mDevice->process(&event, /*count=*/1);
3008 mapper.assertProcessWasNotCalled();
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003009
3010 // All events until the next SYN_REPORT should be dropped.
3011 event.type = EV_KEY;
3012 event.code = KEY_A;
3013 event.value = 1;
3014 unused = mDevice->process(&event, /*count=*/1);
3015 mapper.assertProcessWasNotCalled();
3016
3017 // We get the SYN_REPORT event now, which is not forwarded to mappers.
Arpit Singh4b4a4572023-11-24 18:19:56 +00003018 // This should reset the mapper.
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003019 event.type = EV_SYN;
3020 event.code = SYN_REPORT;
3021 event.value = 0;
3022 unused = mDevice->process(&event, /*count=*/1);
3023 mapper.assertProcessWasNotCalled();
Arpit Singh4b4a4572023-11-24 18:19:56 +00003024 mapper.assertResetWasCalled();
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003025
3026 // The mapper receives events normally now.
3027 event.type = EV_KEY;
3028 event.code = KEY_B;
3029 event.value = 1;
3030 unused = mDevice->process(&event, /*count=*/1);
3031 mapper.assertProcessWasCalled();
3032}
3033
Chris Yef59a2f42020-10-16 12:55:26 -07003034// --- SensorInputMapperTest ---
3035
3036class SensorInputMapperTest : public InputMapperTest {
3037protected:
3038 static const int32_t ACCEL_RAW_MIN;
3039 static const int32_t ACCEL_RAW_MAX;
3040 static const int32_t ACCEL_RAW_FUZZ;
3041 static const int32_t ACCEL_RAW_FLAT;
3042 static const int32_t ACCEL_RAW_RESOLUTION;
3043
3044 static const int32_t GYRO_RAW_MIN;
3045 static const int32_t GYRO_RAW_MAX;
3046 static const int32_t GYRO_RAW_FUZZ;
3047 static const int32_t GYRO_RAW_FLAT;
3048 static const int32_t GYRO_RAW_RESOLUTION;
3049
3050 static const float GRAVITY_MS2_UNIT;
3051 static const float DEGREE_RADIAN_UNIT;
3052
3053 void prepareAccelAxes();
3054 void prepareGyroAxes();
3055 void setAccelProperties();
3056 void setGyroProperties();
3057 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::SENSOR); }
3058};
3059
3060const int32_t SensorInputMapperTest::ACCEL_RAW_MIN = -32768;
3061const int32_t SensorInputMapperTest::ACCEL_RAW_MAX = 32768;
3062const int32_t SensorInputMapperTest::ACCEL_RAW_FUZZ = 16;
3063const int32_t SensorInputMapperTest::ACCEL_RAW_FLAT = 0;
3064const int32_t SensorInputMapperTest::ACCEL_RAW_RESOLUTION = 8192;
3065
3066const int32_t SensorInputMapperTest::GYRO_RAW_MIN = -2097152;
3067const int32_t SensorInputMapperTest::GYRO_RAW_MAX = 2097152;
3068const int32_t SensorInputMapperTest::GYRO_RAW_FUZZ = 16;
3069const int32_t SensorInputMapperTest::GYRO_RAW_FLAT = 0;
3070const int32_t SensorInputMapperTest::GYRO_RAW_RESOLUTION = 1024;
3071
3072const float SensorInputMapperTest::GRAVITY_MS2_UNIT = 9.80665f;
3073const float SensorInputMapperTest::DEGREE_RADIAN_UNIT = 0.0174533f;
3074
3075void SensorInputMapperTest::prepareAccelAxes() {
3076 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3077 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3078 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3079 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3080 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Z, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3081 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3082}
3083
3084void SensorInputMapperTest::prepareGyroAxes() {
3085 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RX, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3086 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3087 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RY, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3088 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3089 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RZ, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3090 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3091}
3092
3093void SensorInputMapperTest::setAccelProperties() {
3094 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 0, InputDeviceSensorType::ACCELEROMETER,
3095 /* sensorDataIndex */ 0);
3096 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 1, InputDeviceSensorType::ACCELEROMETER,
3097 /* sensorDataIndex */ 1);
3098 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 2, InputDeviceSensorType::ACCELEROMETER,
3099 /* sensorDataIndex */ 2);
3100 mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP);
3101 addConfigurationProperty("sensor.accelerometer.reportingMode", "0");
3102 addConfigurationProperty("sensor.accelerometer.maxDelay", "100000");
3103 addConfigurationProperty("sensor.accelerometer.minDelay", "5000");
3104 addConfigurationProperty("sensor.accelerometer.power", "1.5");
3105}
3106
3107void SensorInputMapperTest::setGyroProperties() {
3108 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 3, InputDeviceSensorType::GYROSCOPE,
3109 /* sensorDataIndex */ 0);
3110 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 4, InputDeviceSensorType::GYROSCOPE,
3111 /* sensorDataIndex */ 1);
3112 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 5, InputDeviceSensorType::GYROSCOPE,
3113 /* sensorDataIndex */ 2);
3114 mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP);
3115 addConfigurationProperty("sensor.gyroscope.reportingMode", "0");
3116 addConfigurationProperty("sensor.gyroscope.maxDelay", "100000");
3117 addConfigurationProperty("sensor.gyroscope.minDelay", "5000");
3118 addConfigurationProperty("sensor.gyroscope.power", "0.8");
3119}
3120
3121TEST_F(SensorInputMapperTest, GetSources) {
Arpit Singhfb706c32023-04-26 15:07:55 +00003122 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003123
3124 ASSERT_EQ(static_cast<uint32_t>(AINPUT_SOURCE_SENSOR), mapper.getSources());
3125}
3126
3127TEST_F(SensorInputMapperTest, ProcessAccelerometerSensor) {
3128 setAccelProperties();
3129 prepareAccelAxes();
Arpit Singhfb706c32023-04-26 15:07:55 +00003130 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003131
3132 ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::ACCELEROMETER,
3133 std::chrono::microseconds(10000),
3134 std::chrono::microseconds(0)));
Chris Yee14523a2020-12-19 13:46:00 -08003135 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003136 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, 20000);
3137 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, -20000);
3138 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Z, 40000);
3139 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000);
3140 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Chris Yef59a2f42020-10-16 12:55:26 -07003141
3142 NotifySensorArgs args;
3143 std::vector<float> values = {20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT,
3144 -20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT,
3145 40000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT};
3146
3147 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args));
3148 ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR);
3149 ASSERT_EQ(args.deviceId, DEVICE_ID);
3150 ASSERT_EQ(args.sensorType, InputDeviceSensorType::ACCELEROMETER);
3151 ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH);
3152 ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME);
3153 ASSERT_EQ(args.values, values);
3154 mapper.flushSensor(InputDeviceSensorType::ACCELEROMETER);
3155}
3156
3157TEST_F(SensorInputMapperTest, ProcessGyroscopeSensor) {
3158 setGyroProperties();
3159 prepareGyroAxes();
Arpit Singhfb706c32023-04-26 15:07:55 +00003160 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003161
3162 ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::GYROSCOPE,
3163 std::chrono::microseconds(10000),
3164 std::chrono::microseconds(0)));
Chris Yee14523a2020-12-19 13:46:00 -08003165 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003166 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RX, 20000);
3167 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RY, -20000);
3168 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RZ, 40000);
3169 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000);
3170 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Chris Yef59a2f42020-10-16 12:55:26 -07003171
3172 NotifySensorArgs args;
3173 std::vector<float> values = {20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT,
3174 -20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT,
3175 40000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT};
3176
3177 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args));
3178 ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR);
3179 ASSERT_EQ(args.deviceId, DEVICE_ID);
3180 ASSERT_EQ(args.sensorType, InputDeviceSensorType::GYROSCOPE);
3181 ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH);
3182 ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME);
3183 ASSERT_EQ(args.values, values);
3184 mapper.flushSensor(InputDeviceSensorType::GYROSCOPE);
3185}
3186
Michael Wrightd02c5b62014-02-10 15:10:22 -08003187// --- KeyboardInputMapperTest ---
3188
3189class KeyboardInputMapperTest : public InputMapperTest {
3190protected:
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003191 void SetUp() override {
3192 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
3193 InputDeviceClass::ALPHAKEY);
3194 }
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003195 const std::string UNIQUE_ID = "local:0";
Zixuan Qufecb6062022-11-12 04:44:31 +00003196 const KeyboardLayoutInfo DEVICE_KEYBOARD_LAYOUT_INFO = KeyboardLayoutInfo("en-US", "qwerty");
Michael Wrighta9cf4192022-12-01 23:46:39 +00003197 void prepareDisplay(ui::Rotation orientation);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003198
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003199 void testDPadKeyRotation(KeyboardInputMapper& mapper, int32_t originalScanCode,
Arthur Hung2c9a3342019-07-23 14:18:59 +08003200 int32_t originalKeyCode, int32_t rotatedKeyCode,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003201 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003202};
3203
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003204/* Similar to setDisplayInfoAndReconfigure, but pre-populates all parameters except for the
3205 * orientation.
3206 */
Michael Wrighta9cf4192022-12-01 23:46:39 +00003207void KeyboardInputMapperTest::prepareDisplay(ui::Rotation orientation) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003208 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
3209 NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003210}
3211
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003212void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper& mapper,
Arthur Hung2c9a3342019-07-23 14:18:59 +08003213 int32_t originalScanCode, int32_t originalKeyCode,
Linnan Li13bf76a2024-05-05 19:18:02 +08003214 int32_t rotatedKeyCode,
3215 ui::LogicalDisplayId displayId) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003216 NotifyKeyArgs args;
3217
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003218 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003219 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3220 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3221 ASSERT_EQ(originalScanCode, args.scanCode);
3222 ASSERT_EQ(rotatedKeyCode, args.keyCode);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003223 ASSERT_EQ(displayId, args.displayId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003224
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003225 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003226 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3227 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3228 ASSERT_EQ(originalScanCode, args.scanCode);
3229 ASSERT_EQ(rotatedKeyCode, args.keyCode);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003230 ASSERT_EQ(displayId, args.displayId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003231}
3232
Michael Wrightd02c5b62014-02-10 15:10:22 -08003233TEST_F(KeyboardInputMapperTest, GetSources) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003234 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003235 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003236
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003237 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003238}
3239
3240TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) {
3241 const int32_t USAGE_A = 0x070004;
3242 const int32_t USAGE_UNKNOWN = 0x07ffff;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003243 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3244 mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
Chris Yea52ade12020-08-27 16:49:20 -07003245 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, POLICY_FLAG_WAKE);
3246 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, POLICY_FLAG_WAKE);
3247 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, POLICY_FLAG_WAKE);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003248
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003249 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003250 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003251 // Initial metastate is AMETA_NONE.
3252 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003253
3254 // Key down by scan code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003255 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003256 NotifyKeyArgs args;
3257 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, args.eventTime);
3261 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, 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 up by scan code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003270 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003271 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3272 ASSERT_EQ(DEVICE_ID, args.deviceId);
3273 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3274 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3275 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3276 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3277 ASSERT_EQ(KEY_HOME, args.scanCode);
3278 ASSERT_EQ(AMETA_NONE, args.metaState);
3279 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3280 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3281 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3282
3283 // Key down by usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003284 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A);
3285 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, 0, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003286 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3287 ASSERT_EQ(DEVICE_ID, args.deviceId);
3288 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3289 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3290 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3291 ASSERT_EQ(AKEYCODE_A, args.keyCode);
3292 ASSERT_EQ(0, args.scanCode);
3293 ASSERT_EQ(AMETA_NONE, args.metaState);
3294 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3295 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3296 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3297
3298 // Key up by usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003299 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A);
3300 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003301 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3302 ASSERT_EQ(DEVICE_ID, args.deviceId);
3303 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3304 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3305 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3306 ASSERT_EQ(AKEYCODE_A, args.keyCode);
3307 ASSERT_EQ(0, args.scanCode);
3308 ASSERT_EQ(AMETA_NONE, args.metaState);
3309 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3310 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3311 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3312
3313 // Key down with unknown scan code or usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003314 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
3315 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003316 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3317 ASSERT_EQ(DEVICE_ID, args.deviceId);
3318 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3319 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3320 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3321 ASSERT_EQ(0, args.keyCode);
3322 ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
3323 ASSERT_EQ(AMETA_NONE, args.metaState);
3324 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3325 ASSERT_EQ(0U, args.policyFlags);
3326 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3327
3328 // Key up with unknown scan code or usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003329 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
3330 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_UNKNOWN, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003331 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3332 ASSERT_EQ(DEVICE_ID, args.deviceId);
3333 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3334 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3335 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3336 ASSERT_EQ(0, args.keyCode);
3337 ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
3338 ASSERT_EQ(AMETA_NONE, args.metaState);
3339 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3340 ASSERT_EQ(0U, args.policyFlags);
3341 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3342}
3343
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003344TEST_F(KeyboardInputMapperTest, Process_KeyRemapping) {
3345 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
3346 mFakeEventHub->addKey(EVENTHUB_ID, KEY_B, 0, AKEYCODE_B, 0);
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003347
3348 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003349 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003350
Linnan Lie5657f22024-09-13 21:54:37 +08003351 mFakeEventHub->setKeyRemapping(EVENTHUB_ID, {{AKEYCODE_A, AKEYCODE_B}});
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003352 // Key down by scan code.
3353 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_A, 1);
3354 NotifyKeyArgs args;
3355 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3356 ASSERT_EQ(AKEYCODE_B, args.keyCode);
3357
3358 // Key up by scan code.
3359 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 0);
3360 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3361 ASSERT_EQ(AKEYCODE_B, args.keyCode);
3362}
3363
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003364/**
3365 * Ensure that the readTime is set to the time when the EV_KEY is received.
3366 */
3367TEST_F(KeyboardInputMapperTest, Process_SendsReadTime) {
3368 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3369
3370 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003371 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003372 NotifyKeyArgs args;
3373
3374 // Key down
Harry Cutts33476232023-01-30 19:57:29 +00003375 process(mapper, ARBITRARY_TIME, /*readTime=*/12, EV_KEY, KEY_HOME, 1);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003376 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3377 ASSERT_EQ(12, args.readTime);
3378
3379 // Key up
Harry Cutts33476232023-01-30 19:57:29 +00003380 process(mapper, ARBITRARY_TIME, /*readTime=*/15, EV_KEY, KEY_HOME, 1);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003381 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3382 ASSERT_EQ(15, args.readTime);
3383}
3384
Michael Wrightd02c5b62014-02-10 15:10:22 -08003385TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003386 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFTSHIFT, 0, AKEYCODE_SHIFT_LEFT, 0);
3387 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
Chris Yea52ade12020-08-27 16:49:20 -07003388 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 0);
3389 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0);
3390 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003391
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003392 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003393 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003394
Arthur Hung95f68612022-04-07 14:08:22 +08003395 // Initial metastate is AMETA_NONE.
3396 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003397
3398 // Metakey down.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003399 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003400 NotifyKeyArgs args;
3401 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3402 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003403 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
arthurhungdcef2dc2020-08-11 14:47:50 +08003404 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003405
3406 // Key down.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003407 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003408 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3409 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003410 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003411
3412 // Key up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003413 process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_KEY, KEY_A, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003414 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3415 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003416 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003417
3418 // Metakey up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003419 process(mapper, ARBITRARY_TIME + 3, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003420 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3421 ASSERT_EQ(AMETA_NONE, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003422 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
arthurhungdcef2dc2020-08-11 14:47:50 +08003423 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003424}
3425
3426TEST_F(KeyboardInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateDPad) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003427 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3428 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3429 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3430 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003431
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003432 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003433 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003434
Michael Wrighta9cf4192022-12-01 23:46:39 +00003435 prepareDisplay(ui::ROTATION_90);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003436 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3437 KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
3438 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3439 KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
3440 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3441 KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
3442 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3443 KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
3444}
3445
3446TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003447 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3448 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3449 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3450 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003451
Michael Wrightd02c5b62014-02-10 15:10:22 -08003452 addConfigurationProperty("keyboard.orientationAware", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003453 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003454 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003455
Michael Wrighta9cf4192022-12-01 23:46:39 +00003456 prepareDisplay(ui::ROTATION_0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003457 ASSERT_NO_FATAL_FAILURE(
3458 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
3459 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3460 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3461 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3462 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3463 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3464 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003465
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003466 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003467 prepareDisplay(ui::ROTATION_90);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003468 ASSERT_NO_FATAL_FAILURE(
3469 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3470 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3471 AKEYCODE_DPAD_UP, DISPLAY_ID));
3472 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3473 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3474 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3475 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003476
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003477 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003478 prepareDisplay(ui::ROTATION_180);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003479 ASSERT_NO_FATAL_FAILURE(
3480 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3481 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3482 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3483 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3484 AKEYCODE_DPAD_UP, DISPLAY_ID));
3485 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3486 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003487
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003488 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003489 prepareDisplay(ui::ROTATION_270);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003490 ASSERT_NO_FATAL_FAILURE(
3491 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3492 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3493 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3494 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3495 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3496 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3497 AKEYCODE_DPAD_UP, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003498
3499 // Special case: if orientation changes while key is down, we still emit the same keycode
3500 // in the key up as we did in the key down.
3501 NotifyKeyArgs args;
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003502 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003503 prepareDisplay(ui::ROTATION_270);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003504 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003505 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3506 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3507 ASSERT_EQ(KEY_UP, args.scanCode);
3508 ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
3509
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003510 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003511 prepareDisplay(ui::ROTATION_180);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003512 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003513 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3514 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3515 ASSERT_EQ(KEY_UP, args.scanCode);
3516 ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
3517}
3518
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003519TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_NotOrientationAware) {
3520 // If the keyboard is not orientation aware,
3521 // key events should not be associated with a specific display id
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003522 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003523
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003524 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003525 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003526 NotifyKeyArgs args;
3527
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003528 // Display id should be LogicalDisplayId::INVALID without any display configuration.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003529 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003530 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003531 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003532 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003533 ASSERT_EQ(ui::LogicalDisplayId::INVALID, args.displayId);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003534
Michael Wrighta9cf4192022-12-01 23:46:39 +00003535 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003536 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003537 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003538 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003539 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003540 ASSERT_EQ(ui::LogicalDisplayId::INVALID, args.displayId);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003541}
3542
3543TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_OrientationAware) {
3544 // If the keyboard is orientation aware,
3545 // key events should be associated with the internal viewport
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003546 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003547
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003548 addConfigurationProperty("keyboard.orientationAware", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003549 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003550 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003551 NotifyKeyArgs args;
3552
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003553 // Display id should be LogicalDisplayId::INVALID without any display configuration.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003554 // ^--- already checked by the previous test
3555
Michael Wrighta9cf4192022-12-01 23:46:39 +00003556 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003557 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003558 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003559 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003560 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003561 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3562 ASSERT_EQ(DISPLAY_ID, args.displayId);
3563
Linnan Li13bf76a2024-05-05 19:18:02 +08003564 constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003565 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003566 setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003567 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003568 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003569 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003570 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003571 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3572 ASSERT_EQ(newDisplayId, args.displayId);
3573}
3574
Michael Wrightd02c5b62014-02-10 15:10:22 -08003575TEST_F(KeyboardInputMapperTest, GetKeyCodeState) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003576 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003577 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003578
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003579 mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003580 ASSERT_EQ(1, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003581
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003582 mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003583 ASSERT_EQ(0, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003584}
3585
Philip Junker4af3b3d2021-12-14 10:36:55 +01003586TEST_F(KeyboardInputMapperTest, GetKeyCodeForKeyLocation) {
3587 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003588 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Philip Junker4af3b3d2021-12-14 10:36:55 +01003589
3590 mFakeEventHub->addKeyCodeMapping(EVENTHUB_ID, AKEYCODE_Y, AKEYCODE_Z);
3591 ASSERT_EQ(AKEYCODE_Z, mapper.getKeyCodeForKeyLocation(AKEYCODE_Y))
3592 << "If a mapping is available, the result is equal to the mapping";
3593
3594 ASSERT_EQ(AKEYCODE_A, mapper.getKeyCodeForKeyLocation(AKEYCODE_A))
3595 << "If no mapping is available, the result is the key location";
3596}
3597
Michael Wrightd02c5b62014-02-10 15:10:22 -08003598TEST_F(KeyboardInputMapperTest, GetScanCodeState) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003599 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003600 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003601
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003602 mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003603 ASSERT_EQ(1, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003604
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003605 mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003606 ASSERT_EQ(0, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003607}
3608
3609TEST_F(KeyboardInputMapperTest, MarkSupportedKeyCodes) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003610 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003611 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003612
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003613 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003614
Michael Wrightd02c5b62014-02-10 15:10:22 -08003615 uint8_t flags[2] = { 0, 0 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07003616 ASSERT_TRUE(mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_A, AKEYCODE_B}, flags));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003617 ASSERT_TRUE(flags[0]);
3618 ASSERT_FALSE(flags[1]);
3619}
3620
3621TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003622 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3623 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3624 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3625 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3626 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3627 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003628
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003629 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003630 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003631 // Initial metastate is AMETA_NONE.
3632 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003633
3634 // Initialization should have turned all of the lights off.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003635 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3636 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3637 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003638
3639 // Toggle caps lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003640 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3641 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003642 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3643 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3644 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003645 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003646
3647 // Toggle num lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003648 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3649 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003650 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3651 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3652 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003653 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003654
3655 // Toggle caps lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003656 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3657 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003658 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3659 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3660 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003661 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003662
3663 // Toggle scroll lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003664 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3665 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003666 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3667 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3668 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003669 ASSERT_EQ(AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003670
3671 // Toggle num lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003672 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3673 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003674 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3675 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3676 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003677 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003678
3679 // Toggle scroll lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003680 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3681 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003682 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3683 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3684 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003685 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003686}
3687
Arthur Hung2c9a3342019-07-23 14:18:59 +08003688TEST_F(KeyboardInputMapperTest, Configure_AssignsDisplayPort) {
3689 // keyboard 1.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003690 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3691 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3692 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3693 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003694
3695 // keyboard 2.
3696 const std::string USB2 = "USB2";
arthurhungdcef2dc2020-08-11 14:47:50 +08003697 const std::string DEVICE_NAME2 = "KEYBOARD2";
Arthur Hung2c9a3342019-07-23 14:18:59 +08003698 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003699 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
arthurhungdcef2dc2020-08-11 14:47:50 +08003700 std::shared_ptr<InputDevice> device2 =
3701 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
Dominik Laskowski2f01d772022-03-23 16:01:29 -07003702 ftl::Flags<InputDeviceClass>(0));
arthurhungdcef2dc2020-08-11 14:47:50 +08003703
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003704 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3705 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3706 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3707 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003708
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003709 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003710 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003711
Arpit Singh67ca6842023-04-26 14:43:16 +00003712 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003713 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003714 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3715 mFakePolicy
3716 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003717 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003718 std::list<NotifyArgs> unused =
3719 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003720 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003721 unused += device2->reset(ARBITRARY_TIME);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003722
3723 // Prepared displays and associated info.
3724 constexpr uint8_t hdmi1 = 0;
3725 constexpr uint8_t hdmi2 = 1;
3726 const std::string SECONDARY_UNIQUE_ID = "local:1";
3727
3728 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
3729 mFakePolicy->addInputPortAssociation(USB2, hdmi2);
3730
3731 // No associated display viewport found, should disable the device.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003732 unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003733 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003734 ASSERT_FALSE(device2->isEnabled());
3735
3736 // Prepare second display.
Linnan Li13bf76a2024-05-05 19:18:02 +08003737 constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
Michael Wrighta9cf4192022-12-01 23:46:39 +00003738 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003739 UNIQUE_ID, hdmi1, ViewportType::INTERNAL);
Michael Wrighta9cf4192022-12-01 23:46:39 +00003740 setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003741 SECONDARY_UNIQUE_ID, hdmi2, ViewportType::EXTERNAL);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003742 // Default device will reconfigure above, need additional reconfiguration for another device.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003743 unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003744 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003745
3746 // Device should be enabled after the associated display is found.
3747 ASSERT_TRUE(mDevice->isEnabled());
3748 ASSERT_TRUE(device2->isEnabled());
3749
3750 // Test pad key events
3751 ASSERT_NO_FATAL_FAILURE(
3752 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
3753 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3754 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3755 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3756 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3757 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3758 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3759
3760 ASSERT_NO_FATAL_FAILURE(
3761 testDPadKeyRotation(mapper2, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, newDisplayId));
3762 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3763 AKEYCODE_DPAD_RIGHT, newDisplayId));
3764 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3765 AKEYCODE_DPAD_DOWN, newDisplayId));
3766 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3767 AKEYCODE_DPAD_LEFT, newDisplayId));
3768}
Michael Wrightd02c5b62014-02-10 15:10:22 -08003769
arthurhungc903df12020-08-11 15:08:42 +08003770TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleAfterReattach) {
3771 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3772 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3773 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3774 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3775 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3776 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3777
3778 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003779 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003780 // Initial metastate is AMETA_NONE.
3781 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
arthurhungc903df12020-08-11 15:08:42 +08003782
3783 // Initialization should have turned all of the lights off.
3784 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3785 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3786 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3787
3788 // Toggle caps lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003789 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3790 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003791 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3792 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
3793
3794 // Toggle num lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003795 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3796 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003797 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3798 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
3799
3800 // Toggle scroll lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003801 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3802 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003803 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3804 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
3805
3806 mFakeEventHub->removeDevice(EVENTHUB_ID);
3807 mReader->loopOnce();
3808
3809 // keyboard 2 should default toggle keys.
3810 const std::string USB2 = "USB2";
3811 const std::string DEVICE_NAME2 = "KEYBOARD2";
3812 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
3813 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
3814 std::shared_ptr<InputDevice> device2 =
3815 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
Dominik Laskowski2f01d772022-03-23 16:01:29 -07003816 ftl::Flags<InputDeviceClass>(0));
arthurhungc903df12020-08-11 15:08:42 +08003817 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3818 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
3819 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3820 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3821 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3822 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3823
Arpit Singh67ca6842023-04-26 14:43:16 +00003824 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
arthurhung6fe95782020-10-05 22:41:16 +08003825 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003826 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3827 mFakePolicy
3828 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003829 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003830 std::list<NotifyArgs> unused =
3831 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003832 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003833 unused += device2->reset(ARBITRARY_TIME);
arthurhungc903df12020-08-11 15:08:42 +08003834
3835 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_CAPSL));
3836 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_NUML));
3837 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_SCROLLL));
arthurhung6fe95782020-10-05 22:41:16 +08003838 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON,
3839 mapper2.getMetaState());
arthurhungc903df12020-08-11 15:08:42 +08003840}
3841
Arthur Hungcb40a002021-08-03 14:31:01 +00003842TEST_F(KeyboardInputMapperTest, Process_toggleCapsLockState) {
3843 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3844 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3845 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3846
3847 // Suppose we have two mappers. (DPAD + KEYBOARD)
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003848 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD);
Arthur Hungcb40a002021-08-03 14:31:01 +00003849 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003850 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003851 // Initial metastate is AMETA_NONE.
3852 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Arthur Hungcb40a002021-08-03 14:31:01 +00003853
3854 mReader->toggleCapsLockState(DEVICE_ID);
3855 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
3856}
3857
Arthur Hungfb3cc112022-04-13 07:39:50 +00003858TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleInMultiDevices) {
3859 // keyboard 1.
3860 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3861 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3862 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
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 KeyboardInputMapper& mapper1 =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003868 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hungfb3cc112022-04-13 07:39:50 +00003869
3870 // keyboard 2.
3871 const std::string USB2 = "USB2";
3872 const std::string DEVICE_NAME2 = "KEYBOARD2";
3873 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
3874 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
3875 std::shared_ptr<InputDevice> device2 =
3876 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
3877 ftl::Flags<InputDeviceClass>(0));
3878 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3879 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
3880 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3881 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3882 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3883 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3884
Arpit Singh67ca6842023-04-26 14:43:16 +00003885 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
Arthur Hungfb3cc112022-04-13 07:39:50 +00003886 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003887 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3888 mFakePolicy
3889 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003890 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003891 std::list<NotifyArgs> unused =
3892 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003893 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003894 unused += device2->reset(ARBITRARY_TIME);
Arthur Hungfb3cc112022-04-13 07:39:50 +00003895
Arthur Hung95f68612022-04-07 14:08:22 +08003896 // Initial metastate is AMETA_NONE.
3897 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
3898 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
3899
3900 // Toggle num lock on and off.
3901 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3902 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Arthur Hungfb3cc112022-04-13 07:39:50 +00003903 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3904 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper1.getMetaState());
3905 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper2.getMetaState());
3906
3907 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3908 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
3909 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3910 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
3911 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
3912
3913 // Toggle caps lock on and off.
3914 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3915 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
3916 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3917 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper1.getMetaState());
3918 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper2.getMetaState());
3919
3920 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3921 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
3922 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3923 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
3924 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
3925
3926 // Toggle scroll lock on and off.
3927 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3928 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
3929 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3930 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper1.getMetaState());
3931 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper2.getMetaState());
3932
3933 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3934 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
3935 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3936 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
3937 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
3938}
3939
Arthur Hung2141d542022-08-23 07:45:21 +00003940TEST_F(KeyboardInputMapperTest, Process_DisabledDevice) {
3941 const int32_t USAGE_A = 0x070004;
3942 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3943 mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
3944
3945 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003946 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung2141d542022-08-23 07:45:21 +00003947 // Key down by scan code.
3948 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
3949 NotifyKeyArgs args;
3950 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3951 ASSERT_EQ(DEVICE_ID, args.deviceId);
3952 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3953 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3954 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3955 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3956 ASSERT_EQ(KEY_HOME, args.scanCode);
3957 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3958
3959 // Disable device, it should synthesize cancellation events for down events.
3960 mFakePolicy->addDisabledDevice(DEVICE_ID);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003961 configureDevice(InputReaderConfiguration::Change::ENABLED_STATE);
Arthur Hung2141d542022-08-23 07:45:21 +00003962
3963 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3964 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3965 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3966 ASSERT_EQ(KEY_HOME, args.scanCode);
3967 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_CANCELED, args.flags);
3968}
3969
Zixuan Qufecb6062022-11-12 04:44:31 +00003970TEST_F(KeyboardInputMapperTest, Configure_AssignKeyboardLayoutInfo) {
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003971 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Zixuan Qufecb6062022-11-12 04:44:31 +00003972 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003973 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
3974 /*changes=*/{});
Zixuan Qufecb6062022-11-12 04:44:31 +00003975
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +00003976 uint32_t generation = mReader->getContext()->getGeneration();
Zixuan Qufecb6062022-11-12 04:44:31 +00003977 mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
3978
3979 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003980 InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
Zixuan Qufecb6062022-11-12 04:44:31 +00003981
3982 InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
3983 ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.languageTag,
3984 deviceInfo.getKeyboardLayoutInfo()->languageTag);
3985 ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.layoutType,
3986 deviceInfo.getKeyboardLayoutInfo()->layoutType);
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +00003987 ASSERT_TRUE(mReader->getContext()->getGeneration() != generation);
3988
3989 // Call change layout association with the same values: Generation shouldn't change
3990 generation = mReader->getContext()->getGeneration();
3991 mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
3992 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
3993 InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
3994 ASSERT_TRUE(mReader->getContext()->getGeneration() == generation);
Zixuan Qufecb6062022-11-12 04:44:31 +00003995}
3996
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00003997TEST_F(KeyboardInputMapperTest, LayoutInfoCorrectlyMapped) {
3998 mFakeEventHub->setRawLayoutInfo(EVENTHUB_ID,
3999 RawLayoutInfo{.languageTag = "en", .layoutType = "extended"});
4000
4001 // Configuration
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004002 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004003 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004004 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004005
4006 ASSERT_EQ("en", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->languageTag);
4007 ASSERT_EQ("extended", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->layoutType);
4008}
4009
Justin Chung71ddb432023-03-27 04:29:07 +00004010TEST_F(KeyboardInputMapperTest, Process_GesureEventToSetFlagKeepTouchMode) {
4011 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, POLICY_FLAG_GESTURE);
4012 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004013 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Justin Chung71ddb432023-03-27 04:29:07 +00004014 NotifyKeyArgs args;
4015
4016 // Key down
4017 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFT, 1);
4018 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4019 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_KEEP_TOUCH_MODE, args.flags);
4020}
4021
Prabir Pradhan38636652024-07-23 21:59:36 +00004022/**
4023 * When there is more than one KeyboardInputMapper for an InputDevice, each mapper should produce
4024 * events that use the shared keyboard source across all mappers. This is to ensure that each
4025 * input device generates key events in a consistent manner, regardless of which mapper produces
4026 * the event.
4027 */
4028TEST_F(KeyboardInputMapperTest, UsesSharedKeyboardSource) {
4029 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4030
4031 // Add a mapper with SOURCE_KEYBOARD
4032 KeyboardInputMapper& keyboardMapper =
4033 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
4034
4035 process(keyboardMapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1);
4036 ASSERT_NO_FATAL_FAILURE(
4037 mFakeListener->assertNotifyKeyWasCalled(WithSource(AINPUT_SOURCE_KEYBOARD)));
4038 process(keyboardMapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0);
4039 ASSERT_NO_FATAL_FAILURE(
4040 mFakeListener->assertNotifyKeyWasCalled(WithSource(AINPUT_SOURCE_KEYBOARD)));
4041
4042 // Add a mapper with SOURCE_DPAD
4043 KeyboardInputMapper& dpadMapper =
4044 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD);
4045 for (auto* mapper : {&keyboardMapper, &dpadMapper}) {
4046 process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1);
4047 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
4048 WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD)));
4049 process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0);
4050 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
4051 WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD)));
4052 }
4053
4054 // Add a mapper with SOURCE_GAMEPAD
4055 KeyboardInputMapper& gamepadMapper =
4056 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_GAMEPAD);
4057 for (auto* mapper : {&keyboardMapper, &dpadMapper, &gamepadMapper}) {
4058 process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1);
4059 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
4060 WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD)));
4061 process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0);
4062 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
4063 WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD)));
4064 }
4065}
4066
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004067// --- KeyboardInputMapperTest_ExternalAlphabeticDevice ---
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004068
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004069class KeyboardInputMapperTest_ExternalAlphabeticDevice : public InputMapperTest {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004070protected:
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004071 void SetUp() override {
4072 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
4073 InputDeviceClass::ALPHAKEY | InputDeviceClass::EXTERNAL);
4074 }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004075};
4076
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004077// --- KeyboardInputMapperTest_ExternalNonAlphabeticDevice ---
4078
4079class KeyboardInputMapperTest_ExternalNonAlphabeticDevice : public InputMapperTest {
4080protected:
4081 void SetUp() override {
4082 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
4083 InputDeviceClass::EXTERNAL);
4084 }
4085};
4086
4087TEST_F(KeyboardInputMapperTest_ExternalAlphabeticDevice, WakeBehavior_AlphabeticKeyboard) {
Vaibhav Devmurari16257862023-03-06 10:06:32 +00004088 // For external devices, keys will trigger wake on key down. Media keys should also trigger
4089 // wake if triggered from external devices.
Powei Fengd041c5d2019-05-03 17:11:33 -07004090
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004091 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, 0);
4092 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
4093 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
4094 POLICY_FLAG_WAKE);
Powei Fengd041c5d2019-05-03 17:11:33 -07004095
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004096 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004097 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Powei Fengd041c5d2019-05-03 17:11:33 -07004098
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004099 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004100 NotifyKeyArgs args;
4101 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4102 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4103
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004104 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004105 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4106 ASSERT_EQ(uint32_t(0), args.policyFlags);
4107
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004108 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004109 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Vaibhav Devmurari16257862023-03-06 10:06:32 +00004110 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
Powei Fengd041c5d2019-05-03 17:11:33 -07004111
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004112 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004113 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4114 ASSERT_EQ(uint32_t(0), args.policyFlags);
4115
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004116 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004117 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4118 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4119
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004120 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004121 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4122 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4123}
4124
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004125TEST_F(KeyboardInputMapperTest_ExternalNonAlphabeticDevice, WakeBehavior_NonAlphabeticKeyboard) {
Vaibhav Devmurari2681a812024-01-11 00:15:35 +00004126 // For external devices, keys will trigger wake on key down. Media keys should not trigger
4127 // wake if triggered from external non-alphaebtic keyboard (e.g. headsets).
4128
4129 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
4130 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
4131 POLICY_FLAG_WAKE);
4132
4133 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004134 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmurari2681a812024-01-11 00:15:35 +00004135
4136 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
4137 NotifyKeyArgs args;
4138 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4139 ASSERT_EQ(uint32_t(0), args.policyFlags);
4140
4141 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
4142 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4143 ASSERT_EQ(uint32_t(0), args.policyFlags);
4144
4145 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1);
4146 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4147 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4148
4149 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0);
4150 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4151 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4152}
4153
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004154TEST_F(KeyboardInputMapperTest_ExternalAlphabeticDevice, DoNotWakeByDefaultBehavior) {
Powei Fengd041c5d2019-05-03 17:11:33 -07004155 // Tv Remote key's wake behavior is prescribed by the keylayout file.
Powei Fengd041c5d2019-05-03 17:11:33 -07004156
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004157 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4158 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
4159 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, POLICY_FLAG_WAKE);
Powei Fengd041c5d2019-05-03 17:11:33 -07004160
Powei Fengd041c5d2019-05-03 17:11:33 -07004161 addConfigurationProperty("keyboard.doNotWakeByDefault", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004162 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004163 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Powei Fengd041c5d2019-05-03 17:11:33 -07004164
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004165 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004166 NotifyKeyArgs args;
4167 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4168 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4169
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004170 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004171 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4172 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4173
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004174 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_DOWN, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004175 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4176 ASSERT_EQ(uint32_t(0), args.policyFlags);
4177
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004178 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_DOWN, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004179 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4180 ASSERT_EQ(uint32_t(0), args.policyFlags);
4181
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004182 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004183 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4184 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4185
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004186 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004187 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4188 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4189}
4190
Michael Wrightd02c5b62014-02-10 15:10:22 -08004191// --- TouchInputMapperTest ---
4192
4193class TouchInputMapperTest : public InputMapperTest {
4194protected:
4195 static const int32_t RAW_X_MIN;
4196 static const int32_t RAW_X_MAX;
4197 static const int32_t RAW_Y_MIN;
4198 static const int32_t RAW_Y_MAX;
4199 static const int32_t RAW_TOUCH_MIN;
4200 static const int32_t RAW_TOUCH_MAX;
4201 static const int32_t RAW_TOOL_MIN;
4202 static const int32_t RAW_TOOL_MAX;
4203 static const int32_t RAW_PRESSURE_MIN;
4204 static const int32_t RAW_PRESSURE_MAX;
4205 static const int32_t RAW_ORIENTATION_MIN;
4206 static const int32_t RAW_ORIENTATION_MAX;
4207 static const int32_t RAW_DISTANCE_MIN;
4208 static const int32_t RAW_DISTANCE_MAX;
4209 static const int32_t RAW_TILT_MIN;
4210 static const int32_t RAW_TILT_MAX;
4211 static const int32_t RAW_ID_MIN;
4212 static const int32_t RAW_ID_MAX;
4213 static const int32_t RAW_SLOT_MIN;
4214 static const int32_t RAW_SLOT_MAX;
4215 static const float X_PRECISION;
4216 static const float Y_PRECISION;
Santos Cordonfa5cf462017-04-05 10:37:00 -07004217 static const float X_PRECISION_VIRTUAL;
4218 static const float Y_PRECISION_VIRTUAL;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004219
4220 static const float GEOMETRIC_SCALE;
Jason Gerecke489fda82012-09-07 17:19:40 -07004221 static const TouchAffineTransformation AFFINE_TRANSFORM;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004222
4223 static const VirtualKeyDefinition VIRTUAL_KEYS[2];
4224
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07004225 const std::string UNIQUE_ID = "local:0";
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004226 const std::string SECONDARY_UNIQUE_ID = "local:1";
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07004227
Michael Wrightd02c5b62014-02-10 15:10:22 -08004228 enum Axes {
4229 POSITION = 1 << 0,
4230 TOUCH = 1 << 1,
4231 TOOL = 1 << 2,
4232 PRESSURE = 1 << 3,
4233 ORIENTATION = 1 << 4,
4234 MINOR = 1 << 5,
4235 ID = 1 << 6,
4236 DISTANCE = 1 << 7,
4237 TILT = 1 << 8,
4238 SLOT = 1 << 9,
4239 TOOL_TYPE = 1 << 10,
4240 };
4241
Michael Wrighta9cf4192022-12-01 23:46:39 +00004242 void prepareDisplay(ui::Rotation orientation, std::optional<uint8_t> port = NO_PORT);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004243 void prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port = NO_PORT);
Michael Wrighta9cf4192022-12-01 23:46:39 +00004244 void prepareVirtualDisplay(ui::Rotation orientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004245 void prepareVirtualKeys();
Jason Gerecke489fda82012-09-07 17:19:40 -07004246 void prepareLocationCalibration();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004247 int32_t toRawX(float displayX);
4248 int32_t toRawY(float displayY);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07004249 int32_t toRotatedRawX(float displayX);
4250 int32_t toRotatedRawY(float displayY);
Jason Gerecke489fda82012-09-07 17:19:40 -07004251 float toCookedX(float rawX, float rawY);
4252 float toCookedY(float rawX, float rawY);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004253 float toDisplayX(int32_t rawX);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004254 float toDisplayX(int32_t rawX, int32_t displayWidth);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004255 float toDisplayY(int32_t rawY);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004256 float toDisplayY(int32_t rawY, int32_t displayHeight);
4257
Michael Wrightd02c5b62014-02-10 15:10:22 -08004258};
4259
4260const int32_t TouchInputMapperTest::RAW_X_MIN = 25;
4261const int32_t TouchInputMapperTest::RAW_X_MAX = 1019;
4262const int32_t TouchInputMapperTest::RAW_Y_MIN = 30;
4263const int32_t TouchInputMapperTest::RAW_Y_MAX = 1009;
4264const int32_t TouchInputMapperTest::RAW_TOUCH_MIN = 0;
4265const int32_t TouchInputMapperTest::RAW_TOUCH_MAX = 31;
4266const int32_t TouchInputMapperTest::RAW_TOOL_MIN = 0;
4267const int32_t TouchInputMapperTest::RAW_TOOL_MAX = 15;
Michael Wrightaa449c92017-12-13 21:21:43 +00004268const int32_t TouchInputMapperTest::RAW_PRESSURE_MIN = 0;
4269const int32_t TouchInputMapperTest::RAW_PRESSURE_MAX = 255;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004270const int32_t TouchInputMapperTest::RAW_ORIENTATION_MIN = -7;
4271const int32_t TouchInputMapperTest::RAW_ORIENTATION_MAX = 7;
4272const int32_t TouchInputMapperTest::RAW_DISTANCE_MIN = 0;
4273const int32_t TouchInputMapperTest::RAW_DISTANCE_MAX = 7;
4274const int32_t TouchInputMapperTest::RAW_TILT_MIN = 0;
4275const int32_t TouchInputMapperTest::RAW_TILT_MAX = 150;
4276const int32_t TouchInputMapperTest::RAW_ID_MIN = 0;
4277const int32_t TouchInputMapperTest::RAW_ID_MAX = 9;
4278const int32_t TouchInputMapperTest::RAW_SLOT_MIN = 0;
4279const int32_t TouchInputMapperTest::RAW_SLOT_MAX = 9;
4280const float TouchInputMapperTest::X_PRECISION = float(RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH;
4281const float TouchInputMapperTest::Y_PRECISION = float(RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT;
Santos Cordonfa5cf462017-04-05 10:37:00 -07004282const float TouchInputMapperTest::X_PRECISION_VIRTUAL =
4283 float(RAW_X_MAX - RAW_X_MIN + 1) / VIRTUAL_DISPLAY_WIDTH;
4284const float TouchInputMapperTest::Y_PRECISION_VIRTUAL =
4285 float(RAW_Y_MAX - RAW_Y_MIN + 1) / VIRTUAL_DISPLAY_HEIGHT;
Jason Gerecke489fda82012-09-07 17:19:40 -07004286const TouchAffineTransformation TouchInputMapperTest::AFFINE_TRANSFORM =
4287 TouchAffineTransformation(1, -2, 3, -4, 5, -6);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004288
4289const float TouchInputMapperTest::GEOMETRIC_SCALE =
4290 avg(float(DISPLAY_WIDTH) / (RAW_X_MAX - RAW_X_MIN + 1),
4291 float(DISPLAY_HEIGHT) / (RAW_Y_MAX - RAW_Y_MIN + 1));
4292
4293const VirtualKeyDefinition TouchInputMapperTest::VIRTUAL_KEYS[2] = {
4294 { KEY_HOME, 60, DISPLAY_HEIGHT + 15, 20, 20 },
4295 { KEY_MENU, DISPLAY_HEIGHT - 60, DISPLAY_WIDTH + 15, 20, 20 },
4296};
4297
Michael Wrighta9cf4192022-12-01 23:46:39 +00004298void TouchInputMapperTest::prepareDisplay(ui::Rotation orientation, std::optional<uint8_t> port) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01004299 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
4300 port, ViewportType::INTERNAL);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004301}
4302
4303void TouchInputMapperTest::prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port) {
4304 setDisplayInfoAndReconfigure(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00004305 ui::ROTATION_0, SECONDARY_UNIQUE_ID, port, type);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004306}
4307
Michael Wrighta9cf4192022-12-01 23:46:39 +00004308void TouchInputMapperTest::prepareVirtualDisplay(ui::Rotation orientation) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01004309 setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH, VIRTUAL_DISPLAY_HEIGHT,
4310 orientation, VIRTUAL_DISPLAY_UNIQUE_ID, NO_PORT,
4311 ViewportType::VIRTUAL);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004312}
4313
Michael Wrightd02c5b62014-02-10 15:10:22 -08004314void TouchInputMapperTest::prepareVirtualKeys() {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004315 mFakeEventHub->addVirtualKeyDefinition(EVENTHUB_ID, VIRTUAL_KEYS[0]);
4316 mFakeEventHub->addVirtualKeyDefinition(EVENTHUB_ID, VIRTUAL_KEYS[1]);
4317 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4318 mFakeEventHub->addKey(EVENTHUB_ID, KEY_MENU, 0, AKEYCODE_MENU, POLICY_FLAG_WAKE);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004319}
4320
Jason Gerecke489fda82012-09-07 17:19:40 -07004321void TouchInputMapperTest::prepareLocationCalibration() {
4322 mFakePolicy->setTouchAffineTransformation(AFFINE_TRANSFORM);
4323}
4324
Michael Wrightd02c5b62014-02-10 15:10:22 -08004325int32_t TouchInputMapperTest::toRawX(float displayX) {
4326 return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH + RAW_X_MIN);
4327}
4328
4329int32_t TouchInputMapperTest::toRawY(float displayY) {
4330 return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT + RAW_Y_MIN);
4331}
4332
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07004333int32_t TouchInputMapperTest::toRotatedRawX(float displayX) {
4334 return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_HEIGHT + RAW_X_MIN);
4335}
4336
4337int32_t TouchInputMapperTest::toRotatedRawY(float displayY) {
4338 return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_WIDTH + RAW_Y_MIN);
4339}
4340
Jason Gerecke489fda82012-09-07 17:19:40 -07004341float TouchInputMapperTest::toCookedX(float rawX, float rawY) {
4342 AFFINE_TRANSFORM.applyTo(rawX, rawY);
4343 return rawX;
4344}
4345
4346float TouchInputMapperTest::toCookedY(float rawX, float rawY) {
4347 AFFINE_TRANSFORM.applyTo(rawX, rawY);
4348 return rawY;
4349}
4350
Michael Wrightd02c5b62014-02-10 15:10:22 -08004351float TouchInputMapperTest::toDisplayX(int32_t rawX) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004352 return toDisplayX(rawX, DISPLAY_WIDTH);
4353}
4354
4355float TouchInputMapperTest::toDisplayX(int32_t rawX, int32_t displayWidth) {
4356 return float(rawX - RAW_X_MIN) * displayWidth / (RAW_X_MAX - RAW_X_MIN + 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004357}
4358
4359float TouchInputMapperTest::toDisplayY(int32_t rawY) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004360 return toDisplayY(rawY, DISPLAY_HEIGHT);
4361}
4362
4363float TouchInputMapperTest::toDisplayY(int32_t rawY, int32_t displayHeight) {
4364 return float(rawY - RAW_Y_MIN) * displayHeight / (RAW_Y_MAX - RAW_Y_MIN + 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004365}
4366
4367
4368// --- SingleTouchInputMapperTest ---
4369
4370class SingleTouchInputMapperTest : public TouchInputMapperTest {
4371protected:
4372 void prepareButtons();
4373 void prepareAxes(int axes);
4374
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004375 std::list<NotifyArgs> processDown(SingleTouchInputMapper& mapper, int32_t x, int32_t y);
4376 std::list<NotifyArgs> processMove(SingleTouchInputMapper& mapper, int32_t x, int32_t y);
4377 std::list<NotifyArgs> processUp(SingleTouchInputMapper& mappery);
4378 std::list<NotifyArgs> processPressure(SingleTouchInputMapper& mapper, int32_t pressure);
4379 std::list<NotifyArgs> processToolMajor(SingleTouchInputMapper& mapper, int32_t toolMajor);
4380 std::list<NotifyArgs> processDistance(SingleTouchInputMapper& mapper, int32_t distance);
4381 std::list<NotifyArgs> processTilt(SingleTouchInputMapper& mapper, int32_t tiltX, int32_t tiltY);
4382 std::list<NotifyArgs> processKey(SingleTouchInputMapper& mapper, int32_t code, int32_t value);
4383 std::list<NotifyArgs> processSync(SingleTouchInputMapper& mapper);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004384};
4385
4386void SingleTouchInputMapperTest::prepareButtons() {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004387 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004388}
4389
4390void SingleTouchInputMapperTest::prepareAxes(int axes) {
4391 if (axes & POSITION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004392 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
4393 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004394 }
4395 if (axes & PRESSURE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004396 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_PRESSURE, RAW_PRESSURE_MIN,
4397 RAW_PRESSURE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004398 }
4399 if (axes & TOOL) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004400 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TOOL_WIDTH, RAW_TOOL_MIN, RAW_TOOL_MAX, 0,
4401 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004402 }
4403 if (axes & DISTANCE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004404 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_DISTANCE, RAW_DISTANCE_MIN,
4405 RAW_DISTANCE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004406 }
4407 if (axes & TILT) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004408 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TILT_X, RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
4409 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TILT_Y, RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004410 }
4411}
4412
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004413std::list<NotifyArgs> SingleTouchInputMapperTest::processDown(SingleTouchInputMapper& mapper,
4414 int32_t x, int32_t y) {
4415 std::list<NotifyArgs> args;
4416 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
4417 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, x);
4418 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, y);
4419 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004420}
4421
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004422std::list<NotifyArgs> SingleTouchInputMapperTest::processMove(SingleTouchInputMapper& mapper,
4423 int32_t x, int32_t y) {
4424 std::list<NotifyArgs> args;
4425 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, x);
4426 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, y);
4427 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004428}
4429
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004430std::list<NotifyArgs> SingleTouchInputMapperTest::processUp(SingleTouchInputMapper& mapper) {
4431 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004432}
4433
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004434std::list<NotifyArgs> SingleTouchInputMapperTest::processPressure(SingleTouchInputMapper& mapper,
4435 int32_t pressure) {
4436 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_PRESSURE, pressure);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004437}
4438
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004439std::list<NotifyArgs> SingleTouchInputMapperTest::processToolMajor(SingleTouchInputMapper& mapper,
4440 int32_t toolMajor) {
4441 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TOOL_WIDTH, toolMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004442}
4443
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004444std::list<NotifyArgs> SingleTouchInputMapperTest::processDistance(SingleTouchInputMapper& mapper,
4445 int32_t distance) {
4446 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_DISTANCE, distance);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004447}
4448
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004449std::list<NotifyArgs> SingleTouchInputMapperTest::processTilt(SingleTouchInputMapper& mapper,
4450 int32_t tiltX, int32_t tiltY) {
4451 std::list<NotifyArgs> args;
4452 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TILT_X, tiltX);
4453 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TILT_Y, tiltY);
4454 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004455}
4456
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004457std::list<NotifyArgs> SingleTouchInputMapperTest::processKey(SingleTouchInputMapper& mapper,
4458 int32_t code, int32_t value) {
4459 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004460}
4461
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004462std::list<NotifyArgs> SingleTouchInputMapperTest::processSync(SingleTouchInputMapper& mapper) {
4463 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004464}
4465
Michael Wrightd02c5b62014-02-10 15:10:22 -08004466TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndNotACursor_ReturnsPointer) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004467 prepareButtons();
4468 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00004469 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004470
Josep del Río2d8c79a2023-01-23 19:33:50 +00004471 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004472}
4473
Michael Wrightd02c5b62014-02-10 15:10:22 -08004474TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004475 prepareButtons();
4476 prepareAxes(POSITION);
4477 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00004478 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004479
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004480 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004481}
4482
4483TEST_F(SingleTouchInputMapperTest, GetKeyCodeState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004484 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004485 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004486 prepareButtons();
4487 prepareAxes(POSITION);
4488 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004489 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004490
4491 // Unknown key.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004492 ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004493
4494 // Virtual key is down.
4495 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4496 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4497 processDown(mapper, x, y);
4498 processSync(mapper);
4499 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4500
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004501 ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004502
4503 // Virtual key is up.
4504 processUp(mapper);
4505 processSync(mapper);
4506 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4507
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004508 ASSERT_EQ(AKEY_STATE_UP, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004509}
4510
4511TEST_F(SingleTouchInputMapperTest, GetScanCodeState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004512 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004513 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004514 prepareButtons();
4515 prepareAxes(POSITION);
4516 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004517 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004518
4519 // Unknown key.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004520 ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004521
4522 // Virtual key is down.
4523 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4524 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4525 processDown(mapper, x, y);
4526 processSync(mapper);
4527 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4528
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004529 ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004530
4531 // Virtual key is up.
4532 processUp(mapper);
4533 processSync(mapper);
4534 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4535
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004536 ASSERT_EQ(AKEY_STATE_UP, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004537}
4538
4539TEST_F(SingleTouchInputMapperTest, MarkSupportedKeyCodes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004540 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004541 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004542 prepareButtons();
4543 prepareAxes(POSITION);
4544 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004545 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004546
Michael Wrightd02c5b62014-02-10 15:10:22 -08004547 uint8_t flags[2] = { 0, 0 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07004548 ASSERT_TRUE(
4549 mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_HOME, AKEYCODE_A}, flags));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004550 ASSERT_TRUE(flags[0]);
4551 ASSERT_FALSE(flags[1]);
4552}
4553
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004554TEST_F(SingleTouchInputMapperTest, DeviceTypeChange_RecalculatesRawToDisplayTransform) {
4555 prepareDisplay(ui::ROTATION_0);
4556 prepareAxes(POSITION);
4557 addConfigurationProperty("touch.deviceType", "touchScreen");
4558 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
4559
4560 const int32_t x = 900;
4561 const int32_t y = 75;
4562 std::list<NotifyArgs> args;
4563 args += processDown(mapper, x, y);
4564 args += processSync(mapper);
4565
4566 // Assert that motion event is received in display coordinate space for deviceType touchScreen.
4567 ASSERT_THAT(args,
4568 ElementsAre(VariantWith<NotifyMotionArgs>(
4569 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4570 WithCoords(toDisplayX(x), toDisplayY(y))))));
4571
4572 // Add device type association after the device was created.
4573 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
4574 // Send update to the mapper.
4575 std::list<NotifyArgs> unused =
4576 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
4577 InputReaderConfiguration::Change::DEVICE_TYPE /*changes*/);
4578
4579 args.clear();
4580 args += processDown(mapper, x, y);
4581 args += processSync(mapper);
4582
4583 // Assert that motion event is received in raw coordinate space for deviceType touchNavigation.
4584 ASSERT_THAT(args,
4585 ElementsAre(VariantWith<NotifyMotionArgs>(
4586 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4587 WithCoords(x - RAW_X_MIN, y - RAW_Y_MIN)))));
4588}
4589
Michael Wrightd02c5b62014-02-10 15:10:22 -08004590TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNormally_SendsKeyDownAndKeyUp) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004591 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004592 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004593 prepareButtons();
4594 prepareAxes(POSITION);
4595 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004596 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004597
arthurhungdcef2dc2020-08-11 14:47:50 +08004598 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004599
4600 NotifyKeyArgs args;
4601
4602 // Press virtual key.
4603 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4604 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4605 processDown(mapper, x, y);
4606 processSync(mapper);
4607
4608 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4609 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4610 ASSERT_EQ(DEVICE_ID, args.deviceId);
4611 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4612 ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
4613 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
4614 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
4615 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4616 ASSERT_EQ(KEY_HOME, args.scanCode);
4617 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
4618 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
4619
4620 // Release virtual key.
4621 processUp(mapper);
4622 processSync(mapper);
4623
4624 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4625 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4626 ASSERT_EQ(DEVICE_ID, args.deviceId);
4627 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4628 ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
4629 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
4630 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
4631 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4632 ASSERT_EQ(KEY_HOME, args.scanCode);
4633 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
4634 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
4635
4636 // Should not have sent any motions.
4637 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4638}
4639
4640TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfBounds_SendsKeyDownAndKeyCancel) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004641 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004642 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004643 prepareButtons();
4644 prepareAxes(POSITION);
4645 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004646 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004647
arthurhungdcef2dc2020-08-11 14:47:50 +08004648 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004649
4650 NotifyKeyArgs keyArgs;
4651
4652 // Press virtual key.
4653 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4654 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4655 processDown(mapper, x, y);
4656 processSync(mapper);
4657
4658 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
4659 ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
4660 ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
4661 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
4662 ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
4663 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
4664 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, keyArgs.flags);
4665 ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
4666 ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
4667 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
4668 ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
4669
4670 // Move out of bounds. This should generate a cancel and a pointer down since we moved
4671 // into the display area.
4672 y -= 100;
4673 processMove(mapper, x, y);
4674 processSync(mapper);
4675
4676 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
4677 ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
4678 ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
4679 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
4680 ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
4681 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
4682 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
4683 | AKEY_EVENT_FLAG_CANCELED, keyArgs.flags);
4684 ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
4685 ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
4686 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
4687 ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
4688
4689 NotifyMotionArgs motionArgs;
4690 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4691 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4692 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4693 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4694 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4695 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4696 ASSERT_EQ(0, motionArgs.flags);
4697 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4698 ASSERT_EQ(0, motionArgs.buttonState);
4699 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004700 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004701 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004702 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004703 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4704 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4705 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4706 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4707 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4708
4709 // Keep moving out of bounds. Should generate a pointer move.
4710 y -= 50;
4711 processMove(mapper, x, y);
4712 processSync(mapper);
4713
4714 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4715 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4716 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4717 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4718 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4719 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
4720 ASSERT_EQ(0, motionArgs.flags);
4721 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4722 ASSERT_EQ(0, motionArgs.buttonState);
4723 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004724 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004725 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004726 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004727 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4728 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4729 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4730 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4731 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4732
4733 // Release out of bounds. Should generate a pointer up.
4734 processUp(mapper);
4735 processSync(mapper);
4736
4737 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4738 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4739 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4740 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4741 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4742 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4743 ASSERT_EQ(0, motionArgs.flags);
4744 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4745 ASSERT_EQ(0, motionArgs.buttonState);
4746 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004747 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004748 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004749 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004750 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4751 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4752 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4753 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4754 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4755
4756 // Should not have sent any more keys or motions.
4757 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4758 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4759}
4760
4761TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMovesIn_SendsDownAsTouchEntersDisplay) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004762 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004763 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004764 prepareButtons();
4765 prepareAxes(POSITION);
4766 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004767 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004768
arthurhungdcef2dc2020-08-11 14:47:50 +08004769 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004770
4771 NotifyMotionArgs motionArgs;
4772
4773 // Initially go down out of bounds.
4774 int32_t x = -10;
4775 int32_t y = -10;
4776 processDown(mapper, x, y);
4777 processSync(mapper);
4778
4779 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4780
4781 // Move into the display area. Should generate a pointer down.
4782 x = 50;
4783 y = 75;
4784 processMove(mapper, x, y);
4785 processSync(mapper);
4786
4787 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4788 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4789 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4790 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4791 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4792 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4793 ASSERT_EQ(0, motionArgs.flags);
4794 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4795 ASSERT_EQ(0, motionArgs.buttonState);
4796 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004797 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004798 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004799 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004800 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4801 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4802 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4803 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4804 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4805
4806 // Release. Should generate a pointer up.
4807 processUp(mapper);
4808 processSync(mapper);
4809
4810 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4811 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4812 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4813 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4814 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4815 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4816 ASSERT_EQ(0, motionArgs.flags);
4817 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4818 ASSERT_EQ(0, motionArgs.buttonState);
4819 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004820 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004821 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004822 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004823 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4824 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4825 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4826 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4827 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4828
4829 // Should not have sent any more keys or motions.
4830 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4831 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4832}
4833
Santos Cordonfa5cf462017-04-05 10:37:00 -07004834TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture_VirtualDisplay) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004835 addConfigurationProperty("touch.deviceType", "touchScreen");
4836 addConfigurationProperty("touch.displayId", VIRTUAL_DISPLAY_UNIQUE_ID);
4837
Michael Wrighta9cf4192022-12-01 23:46:39 +00004838 prepareVirtualDisplay(ui::ROTATION_0);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004839 prepareButtons();
4840 prepareAxes(POSITION);
4841 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004842 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Santos Cordonfa5cf462017-04-05 10:37:00 -07004843
arthurhungdcef2dc2020-08-11 14:47:50 +08004844 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004845
4846 NotifyMotionArgs motionArgs;
4847
4848 // Down.
4849 int32_t x = 100;
4850 int32_t y = 125;
4851 processDown(mapper, x, y);
4852 processSync(mapper);
4853
4854 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4855 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4856 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4857 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4858 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4859 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4860 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4861 ASSERT_EQ(0, motionArgs.flags);
4862 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4863 ASSERT_EQ(0, motionArgs.buttonState);
4864 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004865 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004866 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004867 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004868 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4869 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4870 1, 0, 0, 0, 0, 0, 0, 0));
4871 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4872 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4873 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4874
4875 // Move.
4876 x += 50;
4877 y += 75;
4878 processMove(mapper, x, y);
4879 processSync(mapper);
4880
4881 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4882 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4883 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4884 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4885 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4886 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4887 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
4888 ASSERT_EQ(0, motionArgs.flags);
4889 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4890 ASSERT_EQ(0, motionArgs.buttonState);
4891 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004892 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004893 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004894 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004895 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4896 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4897 1, 0, 0, 0, 0, 0, 0, 0));
4898 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4899 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4900 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4901
4902 // Up.
4903 processUp(mapper);
4904 processSync(mapper);
4905
4906 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4907 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4908 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4909 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4910 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4911 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4912 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4913 ASSERT_EQ(0, motionArgs.flags);
4914 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4915 ASSERT_EQ(0, motionArgs.buttonState);
4916 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004917 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004918 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004919 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004920 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4921 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4922 1, 0, 0, 0, 0, 0, 0, 0));
4923 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4924 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4925 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4926
4927 // Should not have sent any more keys or motions.
4928 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4929 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4930}
4931
Michael Wrightd02c5b62014-02-10 15:10:22 -08004932TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004933 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004934 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004935 prepareButtons();
4936 prepareAxes(POSITION);
4937 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004938 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004939
arthurhungdcef2dc2020-08-11 14:47:50 +08004940 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004941
4942 NotifyMotionArgs motionArgs;
4943
4944 // Down.
4945 int32_t x = 100;
4946 int32_t y = 125;
4947 processDown(mapper, x, y);
4948 processSync(mapper);
4949
4950 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4951 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4952 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4953 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4954 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4955 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4956 ASSERT_EQ(0, motionArgs.flags);
4957 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4958 ASSERT_EQ(0, motionArgs.buttonState);
4959 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004960 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004961 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004962 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004963 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4964 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4965 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4966 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4967 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4968
4969 // Move.
4970 x += 50;
4971 y += 75;
4972 processMove(mapper, x, y);
4973 processSync(mapper);
4974
4975 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4976 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4977 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4978 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4979 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4980 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
4981 ASSERT_EQ(0, motionArgs.flags);
4982 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4983 ASSERT_EQ(0, motionArgs.buttonState);
4984 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004985 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004986 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004987 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004988 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4989 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4990 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4991 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4992 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4993
4994 // Up.
4995 processUp(mapper);
4996 processSync(mapper);
4997
4998 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4999 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5000 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5001 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5002 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5003 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5004 ASSERT_EQ(0, motionArgs.flags);
5005 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5006 ASSERT_EQ(0, motionArgs.buttonState);
5007 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005008 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08005009 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005010 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005011 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5012 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
5013 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5014 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5015 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5016
5017 // Should not have sent any more keys or motions.
5018 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5019 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5020}
5021
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005022TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_DoesNotRotateMotions) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005023 addConfigurationProperty("touch.deviceType", "touchScreen");
5024 prepareButtons();
5025 prepareAxes(POSITION);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005026 // InputReader works in the un-rotated coordinate space, so orientation-aware devices do not
5027 // need to be rotated. Touchscreens are orientation-aware by default.
Arpit Singha8c236b2023-04-25 13:56:05 +00005028 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005029
5030 NotifyMotionArgs args;
5031
5032 // Rotation 90.
Michael Wrighta9cf4192022-12-01 23:46:39 +00005033 prepareDisplay(ui::ROTATION_90);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005034 processDown(mapper, toRawX(50), toRawY(75));
5035 processSync(mapper);
5036
5037 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5038 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5039 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5040
5041 processUp(mapper);
5042 processSync(mapper);
5043 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5044}
5045
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005046TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_RotatesMotions) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005047 addConfigurationProperty("touch.deviceType", "touchScreen");
5048 prepareButtons();
5049 prepareAxes(POSITION);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005050 // Since InputReader works in the un-rotated coordinate space, only devices that are not
5051 // orientation-aware are affected by display rotation.
5052 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00005053 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005054
5055 NotifyMotionArgs args;
5056
5057 // Rotation 0.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005058 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005059 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005060 processDown(mapper, toRawX(50), toRawY(75));
5061 processSync(mapper);
5062
5063 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5064 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5065 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5066
5067 processUp(mapper);
5068 processSync(mapper);
5069 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5070
5071 // Rotation 90.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005072 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005073 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005074 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005075 processSync(mapper);
5076
5077 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5078 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5079 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5080
5081 processUp(mapper);
5082 processSync(mapper);
5083 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5084
5085 // Rotation 180.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005086 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005087 prepareDisplay(ui::ROTATION_180);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005088 processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
5089 processSync(mapper);
5090
5091 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5092 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5093 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5094
5095 processUp(mapper);
5096 processSync(mapper);
5097 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5098
5099 // Rotation 270.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005100 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005101 prepareDisplay(ui::ROTATION_270);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005102 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005103 processSync(mapper);
5104
5105 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5106 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5107 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5108
5109 processUp(mapper);
5110 processSync(mapper);
5111 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5112}
5113
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005114TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation0_RotatesMotions) {
5115 addConfigurationProperty("touch.deviceType", "touchScreen");
5116 prepareButtons();
5117 prepareAxes(POSITION);
5118 addConfigurationProperty("touch.orientationAware", "1");
5119 addConfigurationProperty("touch.orientation", "ORIENTATION_0");
5120 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005121 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005122 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005123 NotifyMotionArgs args;
5124
5125 // Orientation 0.
5126 processDown(mapper, toRawX(50), toRawY(75));
5127 processSync(mapper);
5128
5129 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5130 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5131 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5132
5133 processUp(mapper);
5134 processSync(mapper);
5135 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5136}
5137
5138TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation90_RotatesMotions) {
5139 addConfigurationProperty("touch.deviceType", "touchScreen");
5140 prepareButtons();
5141 prepareAxes(POSITION);
5142 addConfigurationProperty("touch.orientationAware", "1");
5143 addConfigurationProperty("touch.orientation", "ORIENTATION_90");
5144 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005145 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005146 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005147 NotifyMotionArgs args;
5148
5149 // Orientation 90.
5150 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
5151 processSync(mapper);
5152
5153 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5154 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5155 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5156
5157 processUp(mapper);
5158 processSync(mapper);
5159 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5160}
5161
5162TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation180_RotatesMotions) {
5163 addConfigurationProperty("touch.deviceType", "touchScreen");
5164 prepareButtons();
5165 prepareAxes(POSITION);
5166 addConfigurationProperty("touch.orientationAware", "1");
5167 addConfigurationProperty("touch.orientation", "ORIENTATION_180");
5168 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005169 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005170 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005171 NotifyMotionArgs args;
5172
5173 // Orientation 180.
5174 processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
5175 processSync(mapper);
5176
5177 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5178 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5179 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5180
5181 processUp(mapper);
5182 processSync(mapper);
5183 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5184}
5185
5186TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation270_RotatesMotions) {
5187 addConfigurationProperty("touch.deviceType", "touchScreen");
5188 prepareButtons();
5189 prepareAxes(POSITION);
5190 addConfigurationProperty("touch.orientationAware", "1");
5191 addConfigurationProperty("touch.orientation", "ORIENTATION_270");
5192 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005193 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005194 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005195 NotifyMotionArgs args;
5196
5197 // Orientation 270.
5198 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
5199 processSync(mapper);
5200
5201 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5202 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5203 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5204
5205 processUp(mapper);
5206 processSync(mapper);
5207 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5208}
5209
5210TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationSpecified_RotatesMotionWithDisplay) {
5211 addConfigurationProperty("touch.deviceType", "touchScreen");
5212 prepareButtons();
5213 prepareAxes(POSITION);
5214 // Since InputReader works in the un-rotated coordinate space, only devices that are not
5215 // orientation-aware are affected by display rotation.
5216 addConfigurationProperty("touch.orientationAware", "0");
5217 addConfigurationProperty("touch.orientation", "ORIENTATION_90");
Arpit Singha8c236b2023-04-25 13:56:05 +00005218 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005219
5220 NotifyMotionArgs args;
5221
5222 // Orientation 90, Rotation 0.
5223 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005224 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005225 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
5226 processSync(mapper);
5227
5228 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5229 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5230 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5231
5232 processUp(mapper);
5233 processSync(mapper);
5234 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5235
5236 // Orientation 90, Rotation 90.
5237 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005238 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005239 processDown(mapper, toRawX(50), toRawY(75));
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005240 processSync(mapper);
5241
5242 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5243 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5244 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5245
5246 processUp(mapper);
5247 processSync(mapper);
5248 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5249
5250 // Orientation 90, Rotation 180.
5251 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005252 prepareDisplay(ui::ROTATION_180);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005253 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
5254 processSync(mapper);
5255
5256 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5257 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5258 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5259
5260 processUp(mapper);
5261 processSync(mapper);
5262 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5263
5264 // Orientation 90, Rotation 270.
5265 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005266 prepareDisplay(ui::ROTATION_270);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005267 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 -07005268 processSync(mapper);
5269
5270 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5271 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5272 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5273
5274 processUp(mapper);
5275 processSync(mapper);
5276 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5277}
5278
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005279TEST_F(SingleTouchInputMapperTest, Process_IgnoresTouchesOutsidePhysicalFrame) {
5280 addConfigurationProperty("touch.deviceType", "touchScreen");
5281 prepareButtons();
5282 prepareAxes(POSITION);
5283 addConfigurationProperty("touch.orientationAware", "1");
5284 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005285 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005286
5287 // Set a physical frame in the display viewport.
5288 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
5289 viewport->physicalLeft = 20;
5290 viewport->physicalTop = 600;
5291 viewport->physicalRight = 30;
5292 viewport->physicalBottom = 610;
5293 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00005294 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005295
5296 // Start the touch.
5297 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
5298 processSync(mapper);
5299
5300 // Expect all input starting outside the physical frame to be ignored.
5301 const std::array<Point, 6> outsidePoints = {
5302 {{0, 0}, {19, 605}, {31, 605}, {25, 599}, {25, 611}, {DISPLAY_WIDTH, DISPLAY_HEIGHT}}};
5303 for (const auto& p : outsidePoints) {
5304 processMove(mapper, toRawX(p.x), toRawY(p.y));
5305 processSync(mapper);
5306 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5307 }
5308
5309 // Move the touch into the physical frame.
5310 processMove(mapper, toRawX(25), toRawY(605));
5311 processSync(mapper);
5312 NotifyMotionArgs args;
5313 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5314 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
5315 EXPECT_NEAR(25, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5316 EXPECT_NEAR(605, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5317
5318 // Once the touch down is reported, continue reporting input, even if it is outside the frame.
5319 for (const auto& p : outsidePoints) {
5320 processMove(mapper, toRawX(p.x), toRawY(p.y));
5321 processSync(mapper);
5322 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5323 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
5324 EXPECT_NEAR(p.x, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5325 EXPECT_NEAR(p.y, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5326 }
5327
5328 processUp(mapper);
5329 processSync(mapper);
5330 EXPECT_NO_FATAL_FAILURE(
5331 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
5332}
5333
Harry Cutts1db43992023-06-19 17:05:07 +00005334TEST_F(SingleTouchInputMapperTest, Process_DoesntCheckPhysicalFrameForTouchpads) {
Harry Cutts1db43992023-06-19 17:05:07 +00005335 addConfigurationProperty("touch.deviceType", "pointer");
5336 prepareAxes(POSITION);
5337 prepareDisplay(ui::ROTATION_0);
5338 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
5339
5340 // Set a physical frame in the display viewport.
5341 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
5342 viewport->physicalLeft = 20;
5343 viewport->physicalTop = 600;
5344 viewport->physicalRight = 30;
5345 viewport->physicalBottom = 610;
5346 mFakePolicy->updateViewport(*viewport);
5347 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
5348
5349 // Start the touch.
5350 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
5351 processSync(mapper);
5352
5353 // Expect all input starting outside the physical frame to result in NotifyMotionArgs being
5354 // produced.
5355 const std::array<Point, 6> outsidePoints = {
5356 {{0, 0}, {19, 605}, {31, 605}, {25, 599}, {25, 611}, {DISPLAY_WIDTH, DISPLAY_HEIGHT}}};
5357 for (const auto& p : outsidePoints) {
5358 processMove(mapper, toRawX(p.x), toRawY(p.y));
5359 processSync(mapper);
5360 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5361 }
5362}
5363
Michael Wrightd02c5b62014-02-10 15:10:22 -08005364TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005365 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005366 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005367 prepareButtons();
5368 prepareAxes(POSITION | PRESSURE | TOOL | DISTANCE | TILT);
Arpit Singha8c236b2023-04-25 13:56:05 +00005369 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005370
5371 // These calculations are based on the input device calibration documentation.
5372 int32_t rawX = 100;
5373 int32_t rawY = 200;
5374 int32_t rawPressure = 10;
5375 int32_t rawToolMajor = 12;
5376 int32_t rawDistance = 2;
5377 int32_t rawTiltX = 30;
5378 int32_t rawTiltY = 110;
5379
5380 float x = toDisplayX(rawX);
5381 float y = toDisplayY(rawY);
5382 float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
5383 float size = float(rawToolMajor) / RAW_TOOL_MAX;
5384 float tool = float(rawToolMajor) * GEOMETRIC_SCALE;
5385 float distance = float(rawDistance);
5386
5387 float tiltCenter = (RAW_TILT_MAX + RAW_TILT_MIN) * 0.5f;
5388 float tiltScale = M_PI / 180;
5389 float tiltXAngle = (rawTiltX - tiltCenter) * tiltScale;
5390 float tiltYAngle = (rawTiltY - tiltCenter) * tiltScale;
5391 float orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
5392 float tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
5393
5394 processDown(mapper, rawX, rawY);
5395 processPressure(mapper, rawPressure);
5396 processToolMajor(mapper, rawToolMajor);
5397 processDistance(mapper, rawDistance);
5398 processTilt(mapper, rawTiltX, rawTiltY);
5399 processSync(mapper);
5400
5401 NotifyMotionArgs args;
5402 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5403 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
5404 x, y, pressure, size, tool, tool, tool, tool, orientation, distance));
5405 ASSERT_EQ(tilt, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TILT));
Prabir Pradhan9a53b552024-06-04 02:59:40 +00005406 ASSERT_EQ(args.flags,
5407 AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION |
5408 AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005409}
5410
Jason Gerecke489fda82012-09-07 17:19:40 -07005411TEST_F(SingleTouchInputMapperTest, Process_XYAxes_AffineCalibration) {
Jason Gerecke489fda82012-09-07 17:19:40 -07005412 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005413 prepareDisplay(ui::ROTATION_0);
Jason Gerecke489fda82012-09-07 17:19:40 -07005414 prepareLocationCalibration();
5415 prepareButtons();
5416 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005417 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Jason Gerecke489fda82012-09-07 17:19:40 -07005418
5419 int32_t rawX = 100;
5420 int32_t rawY = 200;
5421
5422 float x = toDisplayX(toCookedX(rawX, rawY));
5423 float y = toDisplayY(toCookedY(rawX, rawY));
5424
5425 processDown(mapper, rawX, rawY);
5426 processSync(mapper);
5427
5428 NotifyMotionArgs args;
5429 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5430 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
5431 x, y, 1, 0, 0, 0, 0, 0, 0, 0));
5432}
5433
Michael Wrightd02c5b62014-02-10 15:10:22 -08005434TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllButtons) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005435 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005436 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005437 prepareButtons();
5438 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005439 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005440
5441 NotifyMotionArgs motionArgs;
5442 NotifyKeyArgs keyArgs;
5443
5444 processDown(mapper, 100, 200);
5445 processSync(mapper);
5446 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5447 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5448 ASSERT_EQ(0, motionArgs.buttonState);
5449
5450 // press BTN_LEFT, release BTN_LEFT
5451 processKey(mapper, BTN_LEFT, 1);
5452 processSync(mapper);
5453 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5454 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5455 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
5456
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005457 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5458 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5459 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
5460
Michael Wrightd02c5b62014-02-10 15:10:22 -08005461 processKey(mapper, BTN_LEFT, 0);
5462 processSync(mapper);
5463 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005464 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005465 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005466
5467 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005468 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005469 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005470
5471 // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
5472 processKey(mapper, BTN_RIGHT, 1);
5473 processKey(mapper, BTN_MIDDLE, 1);
5474 processSync(mapper);
5475 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5476 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5477 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
5478 motionArgs.buttonState);
5479
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005480 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5481 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5482 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
5483
5484 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5485 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5486 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
5487 motionArgs.buttonState);
5488
Michael Wrightd02c5b62014-02-10 15:10:22 -08005489 processKey(mapper, BTN_RIGHT, 0);
5490 processSync(mapper);
5491 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005492 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005493 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005494
5495 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005496 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005497 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005498
5499 processKey(mapper, BTN_MIDDLE, 0);
5500 processSync(mapper);
5501 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005502 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005503 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005504
5505 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005506 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005507 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005508
5509 // press BTN_BACK, release BTN_BACK
5510 processKey(mapper, BTN_BACK, 1);
5511 processSync(mapper);
5512 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5513 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5514 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005515
Michael Wrightd02c5b62014-02-10 15:10:22 -08005516 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005517 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005518 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
5519
5520 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5521 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5522 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005523
5524 processKey(mapper, BTN_BACK, 0);
5525 processSync(mapper);
5526 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005527 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005528 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005529
5530 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005531 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005532 ASSERT_EQ(0, motionArgs.buttonState);
5533
Michael Wrightd02c5b62014-02-10 15:10:22 -08005534 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5535 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5536 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
5537
5538 // press BTN_SIDE, release BTN_SIDE
5539 processKey(mapper, BTN_SIDE, 1);
5540 processSync(mapper);
5541 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5542 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5543 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005544
Michael Wrightd02c5b62014-02-10 15:10:22 -08005545 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005546 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005547 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
5548
5549 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5550 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5551 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005552
5553 processKey(mapper, BTN_SIDE, 0);
5554 processSync(mapper);
5555 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005556 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005557 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005558
5559 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005560 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005561 ASSERT_EQ(0, motionArgs.buttonState);
5562
Michael Wrightd02c5b62014-02-10 15:10:22 -08005563 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5564 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5565 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
5566
5567 // press BTN_FORWARD, release BTN_FORWARD
5568 processKey(mapper, BTN_FORWARD, 1);
5569 processSync(mapper);
5570 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5571 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5572 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005573
Michael Wrightd02c5b62014-02-10 15:10:22 -08005574 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005575 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005576 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
5577
5578 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5579 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5580 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005581
5582 processKey(mapper, BTN_FORWARD, 0);
5583 processSync(mapper);
5584 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005585 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005586 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005587
5588 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005589 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005590 ASSERT_EQ(0, motionArgs.buttonState);
5591
Michael Wrightd02c5b62014-02-10 15:10:22 -08005592 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5593 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5594 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
5595
5596 // press BTN_EXTRA, release BTN_EXTRA
5597 processKey(mapper, BTN_EXTRA, 1);
5598 processSync(mapper);
5599 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5600 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5601 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005602
Michael Wrightd02c5b62014-02-10 15:10:22 -08005603 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005604 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005605 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
5606
5607 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5608 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5609 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005610
5611 processKey(mapper, BTN_EXTRA, 0);
5612 processSync(mapper);
5613 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005614 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005615 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005616
5617 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005618 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005619 ASSERT_EQ(0, motionArgs.buttonState);
5620
Michael Wrightd02c5b62014-02-10 15:10:22 -08005621 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5622 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5623 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
5624
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005625 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5626
Michael Wrightd02c5b62014-02-10 15:10:22 -08005627 // press BTN_STYLUS, release BTN_STYLUS
5628 processKey(mapper, BTN_STYLUS, 1);
5629 processSync(mapper);
5630 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5631 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005632 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
5633
5634 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5635 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5636 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005637
5638 processKey(mapper, BTN_STYLUS, 0);
5639 processSync(mapper);
5640 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005641 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005642 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005643
5644 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005645 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005646 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005647
5648 // press BTN_STYLUS2, release BTN_STYLUS2
5649 processKey(mapper, BTN_STYLUS2, 1);
5650 processSync(mapper);
5651 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5652 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005653 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
5654
5655 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5656 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5657 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005658
5659 processKey(mapper, BTN_STYLUS2, 0);
5660 processSync(mapper);
5661 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005662 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005663 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005664
5665 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005666 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005667 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005668
5669 // release touch
5670 processUp(mapper);
5671 processSync(mapper);
5672 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5673 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5674 ASSERT_EQ(0, motionArgs.buttonState);
5675}
5676
5677TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005678 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005679 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005680 prepareButtons();
5681 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005682 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005683
5684 NotifyMotionArgs motionArgs;
5685
5686 // default tool type is finger
5687 processDown(mapper, 100, 200);
5688 processSync(mapper);
5689 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5690 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005691 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005692
5693 // eraser
5694 processKey(mapper, BTN_TOOL_RUBBER, 1);
5695 processSync(mapper);
5696 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5697 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005698 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005699
5700 // stylus
5701 processKey(mapper, BTN_TOOL_RUBBER, 0);
5702 processKey(mapper, BTN_TOOL_PEN, 1);
5703 processSync(mapper);
5704 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5705 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005706 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005707
5708 // brush
5709 processKey(mapper, BTN_TOOL_PEN, 0);
5710 processKey(mapper, BTN_TOOL_BRUSH, 1);
5711 processSync(mapper);
5712 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5713 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005714 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005715
5716 // pencil
5717 processKey(mapper, BTN_TOOL_BRUSH, 0);
5718 processKey(mapper, BTN_TOOL_PENCIL, 1);
5719 processSync(mapper);
5720 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5721 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005722 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005723
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08005724 // air-brush
Michael Wrightd02c5b62014-02-10 15:10:22 -08005725 processKey(mapper, BTN_TOOL_PENCIL, 0);
5726 processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
5727 processSync(mapper);
5728 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5729 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005730 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005731
5732 // mouse
5733 processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
5734 processKey(mapper, BTN_TOOL_MOUSE, 1);
5735 processSync(mapper);
5736 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5737 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005738 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005739
5740 // lens
5741 processKey(mapper, BTN_TOOL_MOUSE, 0);
5742 processKey(mapper, BTN_TOOL_LENS, 1);
5743 processSync(mapper);
5744 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5745 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005746 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005747
5748 // double-tap
5749 processKey(mapper, BTN_TOOL_LENS, 0);
5750 processKey(mapper, BTN_TOOL_DOUBLETAP, 1);
5751 processSync(mapper);
5752 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5753 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005754 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005755
5756 // triple-tap
5757 processKey(mapper, BTN_TOOL_DOUBLETAP, 0);
5758 processKey(mapper, BTN_TOOL_TRIPLETAP, 1);
5759 processSync(mapper);
5760 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5761 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005762 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005763
5764 // quad-tap
5765 processKey(mapper, BTN_TOOL_TRIPLETAP, 0);
5766 processKey(mapper, BTN_TOOL_QUADTAP, 1);
5767 processSync(mapper);
5768 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5769 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005770 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005771
5772 // finger
5773 processKey(mapper, BTN_TOOL_QUADTAP, 0);
5774 processKey(mapper, BTN_TOOL_FINGER, 1);
5775 processSync(mapper);
5776 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5777 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005778 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005779
5780 // stylus trumps finger
5781 processKey(mapper, BTN_TOOL_PEN, 1);
5782 processSync(mapper);
5783 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5784 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005785 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005786
5787 // eraser trumps stylus
5788 processKey(mapper, BTN_TOOL_RUBBER, 1);
5789 processSync(mapper);
5790 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5791 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005792 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005793
5794 // mouse trumps eraser
5795 processKey(mapper, BTN_TOOL_MOUSE, 1);
5796 processSync(mapper);
5797 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5798 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005799 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005800
5801 // back to default tool type
5802 processKey(mapper, BTN_TOOL_MOUSE, 0);
5803 processKey(mapper, BTN_TOOL_RUBBER, 0);
5804 processKey(mapper, BTN_TOOL_PEN, 0);
5805 processKey(mapper, BTN_TOOL_FINGER, 0);
5806 processSync(mapper);
5807 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5808 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005809 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005810}
5811
5812TEST_F(SingleTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005813 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005814 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005815 prepareButtons();
5816 prepareAxes(POSITION);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08005817 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_FINGER, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005818 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005819
5820 NotifyMotionArgs motionArgs;
5821
5822 // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0
5823 processKey(mapper, BTN_TOOL_FINGER, 1);
5824 processMove(mapper, 100, 200);
5825 processSync(mapper);
5826 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5827 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5828 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5829 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5830
5831 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5832 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5833 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5834 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5835
5836 // move a little
5837 processMove(mapper, 150, 250);
5838 processSync(mapper);
5839 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5840 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5841 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5842 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5843
5844 // down when BTN_TOUCH is pressed, pressure defaults to 1
5845 processKey(mapper, BTN_TOUCH, 1);
5846 processSync(mapper);
5847 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5848 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5849 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5850 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5851
5852 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5853 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5854 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5855 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5856
5857 // up when BTN_TOUCH is released, hover restored
5858 processKey(mapper, BTN_TOUCH, 0);
5859 processSync(mapper);
5860 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5861 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5862 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5863 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5864
5865 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5866 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5867 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5868 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5869
5870 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5871 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5872 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5873 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5874
5875 // exit hover when pointer goes away
5876 processKey(mapper, BTN_TOOL_FINGER, 0);
5877 processSync(mapper);
5878 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5879 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5880 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5881 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5882}
5883
5884TEST_F(SingleTouchInputMapperTest, Process_WhenAbsPressureIsPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005885 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005886 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005887 prepareButtons();
5888 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00005889 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005890
5891 NotifyMotionArgs motionArgs;
5892
5893 // initially hovering because pressure is 0
5894 processDown(mapper, 100, 200);
5895 processPressure(mapper, 0);
5896 processSync(mapper);
5897 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5898 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5899 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5900 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5901
5902 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5903 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5904 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5905 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5906
5907 // move a little
5908 processMove(mapper, 150, 250);
5909 processSync(mapper);
5910 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5911 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5912 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5913 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5914
5915 // down when pressure is non-zero
5916 processPressure(mapper, RAW_PRESSURE_MAX);
5917 processSync(mapper);
5918 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5919 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5920 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5921 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5922
5923 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5924 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5925 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5926 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5927
5928 // up when pressure becomes 0, hover restored
5929 processPressure(mapper, 0);
5930 processSync(mapper);
5931 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5932 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5933 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5934 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5935
5936 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5937 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5938 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5939 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5940
5941 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5942 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5943 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5944 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5945
5946 // exit hover when pointer goes away
5947 processUp(mapper);
5948 processSync(mapper);
5949 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5950 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5951 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5952 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5953}
5954
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00005955TEST_F(SingleTouchInputMapperTest, Reset_CancelsOngoingGesture) {
5956 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005957 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00005958 prepareButtons();
5959 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00005960 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00005961
5962 // Touch down.
5963 processDown(mapper, 100, 200);
5964 processPressure(mapper, 1);
5965 processSync(mapper);
5966 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
5967 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
5968
5969 // Reset the mapper. This should cancel the ongoing gesture.
5970 resetMapper(mapper, ARBITRARY_TIME);
5971 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
5972 WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
5973
5974 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5975}
5976
Prabir Pradhanafabcde2022-09-27 19:32:43 +00005977TEST_F(SingleTouchInputMapperTest, Reset_RecreatesTouchState) {
5978 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005979 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00005980 prepareButtons();
5981 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00005982 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00005983
5984 // Set the initial state for the touch pointer.
5985 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_X, 100);
5986 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_Y, 200);
5987 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_PRESSURE, RAW_PRESSURE_MAX);
5988 mFakeEventHub->setScanCodeState(EVENTHUB_ID, BTN_TOUCH, 1);
5989
5990 // Reset the mapper. When the mapper is reset, we expect it to attempt to recreate the touch
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00005991 // state by reading the current axis values. Since there was no ongoing gesture, calling reset
5992 // does not generate any events.
5993 resetMapper(mapper, ARBITRARY_TIME);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00005994
5995 // Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
5996 // the recreated touch state to generate a down event.
5997 processSync(mapper);
5998 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
5999 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPressure(1.f))));
6000
6001 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6002}
6003
lilinnan687e58f2022-07-19 16:00:50 +08006004TEST_F(SingleTouchInputMapperTest,
6005 Process_WhenViewportDisplayIdChanged_TouchIsCanceledAndDeviceIsReset) {
6006 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006007 prepareDisplay(ui::ROTATION_0);
lilinnan687e58f2022-07-19 16:00:50 +08006008 prepareButtons();
6009 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006010 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
lilinnan687e58f2022-07-19 16:00:50 +08006011 NotifyMotionArgs motionArgs;
6012
6013 // Down.
Prabir Pradhan3e5ec702022-07-29 16:26:24 +00006014 processDown(mapper, 100, 200);
lilinnan687e58f2022-07-19 16:00:50 +08006015 processSync(mapper);
6016
6017 // We should receive a down event
6018 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6019 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6020
6021 // Change display id
6022 clearViewports();
6023 prepareSecondaryDisplay(ViewportType::INTERNAL);
6024
6025 // We should receive a cancel event
6026 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6027 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
6028 // Then receive reset called
6029 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6030}
6031
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006032TEST_F(SingleTouchInputMapperTest,
6033 Process_WhenViewportActiveStatusChanged_TouchIsCanceledAndDeviceIsReset) {
6034 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006035 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006036 prepareButtons();
6037 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006038 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006039 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6040 NotifyMotionArgs motionArgs;
6041
6042 // Start a new gesture.
6043 processDown(mapper, 100, 200);
6044 processSync(mapper);
6045 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6046 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6047
6048 // Make the viewport inactive. This will put the device in disabled mode.
6049 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6050 viewport->isActive = false;
6051 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006052 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006053
6054 // We should receive a cancel event for the ongoing gesture.
6055 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6056 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
6057 // Then we should be notified that the device was reset.
6058 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6059
6060 // No events are generated while the viewport is inactive.
6061 processMove(mapper, 101, 201);
6062 processSync(mapper);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006063 processUp(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006064 processSync(mapper);
6065 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6066
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006067 // Start a new gesture while the viewport is still inactive.
6068 processDown(mapper, 300, 400);
6069 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_X, 300);
6070 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_Y, 400);
6071 mFakeEventHub->setScanCodeState(EVENTHUB_ID, BTN_TOUCH, 1);
6072 processSync(mapper);
6073
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006074 // Make the viewport active again. The device should resume processing events.
6075 viewport->isActive = true;
6076 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006077 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006078
6079 // The device is reset because it changes back to direct mode, without generating any events.
6080 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6081 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6082
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006083 // In the next sync, the touch state that was recreated when the device was reset is reported.
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006084 processSync(mapper);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006085 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6086 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006087
6088 // No more events.
6089 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6090 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
6091}
6092
Prabir Pradhan211ba622022-10-31 21:09:21 +00006093TEST_F(SingleTouchInputMapperTest, ButtonIsReleasedOnTouchUp) {
6094 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006095 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan211ba622022-10-31 21:09:21 +00006096 prepareButtons();
6097 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006098 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan211ba622022-10-31 21:09:21 +00006099 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6100
6101 // Press a stylus button.
6102 processKey(mapper, BTN_STYLUS, 1);
6103 processSync(mapper);
6104
6105 // Start a touch gesture and ensure the BUTTON_PRESS event is generated.
6106 processDown(mapper, 100, 200);
6107 processSync(mapper);
6108 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6109 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6110 WithCoords(toDisplayX(100), toDisplayY(200)),
6111 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6112 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6113 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
6114 WithCoords(toDisplayX(100), toDisplayY(200)),
6115 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6116
6117 // Release the touch gesture. Ensure that the BUTTON_RELEASE event is generated even though
6118 // the button has not actually been released, since there will be no pointers through which the
6119 // button state can be reported. The event is generated at the location of the pointer before
6120 // it went up.
6121 processUp(mapper);
6122 processSync(mapper);
6123 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6124 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
6125 WithCoords(toDisplayX(100), toDisplayY(200)), WithButtonState(0))));
6126 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6127 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6128 WithCoords(toDisplayX(100), toDisplayY(200)), WithButtonState(0))));
6129}
6130
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00006131TEST_F(SingleTouchInputMapperTest, StylusButtonMotionEventsDisabled) {
6132 addConfigurationProperty("touch.deviceType", "touchScreen");
6133 prepareDisplay(ui::ROTATION_0);
6134 prepareButtons();
6135 prepareAxes(POSITION);
6136
6137 mFakePolicy->setStylusButtonMotionEventsEnabled(false);
6138
Arpit Singha8c236b2023-04-25 13:56:05 +00006139 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00006140 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6141
6142 // Press a stylus button.
6143 processKey(mapper, BTN_STYLUS, 1);
6144 processSync(mapper);
6145
6146 // Start a touch gesture and ensure that the stylus button is not reported.
6147 processDown(mapper, 100, 200);
6148 processSync(mapper);
6149 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6150 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithButtonState(0))));
6151
6152 // Release and press the stylus button again.
6153 processKey(mapper, BTN_STYLUS, 0);
6154 processSync(mapper);
6155 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6156 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
6157 processKey(mapper, BTN_STYLUS, 1);
6158 processSync(mapper);
6159 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6160 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
6161
6162 // Release the touch gesture.
6163 processUp(mapper);
6164 processSync(mapper);
6165 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6166 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
6167
6168 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6169}
6170
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006171TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsSetToTouchNavigation_setsCorrectType) {
6172 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
6173 prepareDisplay(ui::ROTATION_0);
6174 prepareButtons();
6175 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006176 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006177 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6178
Prabir Pradhan9cf8f322024-06-18 20:22:42 +00006179 ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION | AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006180}
6181
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006182TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsChangedToTouchNavigation_updatesDeviceType) {
6183 // Initialize the device without setting device source to touch navigation.
6184 addConfigurationProperty("touch.deviceType", "touchScreen");
6185 prepareDisplay(ui::ROTATION_0);
6186 prepareButtons();
6187 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006188 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006189
6190 // Ensure that the device is created as a touchscreen, not touch navigation.
6191 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
6192
6193 // Add device type association after the device was created.
6194 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
6195
6196 // Send update to the mapper.
6197 std::list<NotifyArgs> unused2 =
6198 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006199 InputReaderConfiguration::Change::DEVICE_TYPE /*changes*/);
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006200
6201 // Check whether device type update was successful.
Prabir Pradhan9cf8f322024-06-18 20:22:42 +00006202 ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION | AINPUT_SOURCE_TOUCHPAD, mDevice->getSources());
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006203}
6204
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006205TEST_F(SingleTouchInputMapperTest, HoverEventsOutsidePhysicalFrameAreIgnored) {
6206 // Initialize the device without setting device source to touch navigation.
6207 addConfigurationProperty("touch.deviceType", "touchScreen");
6208 prepareDisplay(ui::ROTATION_0);
6209 prepareButtons();
6210 prepareAxes(POSITION);
6211 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
6212
6213 // Set a physical frame in the display viewport.
6214 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6215 viewport->physicalLeft = 0;
6216 viewport->physicalTop = 0;
6217 viewport->physicalRight = DISPLAY_WIDTH / 2;
6218 viewport->physicalBottom = DISPLAY_HEIGHT / 2;
6219 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006220 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006221
Arpit Singha8c236b2023-04-25 13:56:05 +00006222 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006223
6224 // Hovering inside the physical frame produces events.
6225 processKey(mapper, BTN_TOOL_PEN, 1);
6226 processMove(mapper, RAW_X_MIN + 1, RAW_Y_MIN + 1);
6227 processSync(mapper);
6228 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6229 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)));
6230 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6231 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)));
6232
6233 // Leaving the physical frame ends the hovering gesture.
6234 processMove(mapper, RAW_X_MAX - 1, RAW_Y_MAX - 1);
6235 processSync(mapper);
6236 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6237 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT)));
6238
6239 // Moving outside the physical frame does not produce events.
6240 processMove(mapper, RAW_X_MAX - 2, RAW_Y_MAX - 2);
6241 processSync(mapper);
6242 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6243
6244 // Re-entering the physical frame produces events.
6245 processMove(mapper, RAW_X_MIN, RAW_Y_MIN);
6246 processSync(mapper);
6247 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6248 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)));
6249 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6250 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)));
6251}
6252
Prabir Pradhan5632d622021-09-06 07:57:20 -07006253// --- TouchDisplayProjectionTest ---
6254
6255class TouchDisplayProjectionTest : public SingleTouchInputMapperTest {
6256public:
6257 // The values inside DisplayViewport are expected to be pre-rotated. This updates the current
6258 // DisplayViewport to pre-rotate the values. The viewport's physical display will be set to the
6259 // rotated equivalent of the given un-rotated physical display bounds.
Prabir Pradhana9df3162022-12-05 23:57:27 +00006260 void configurePhysicalDisplay(ui::Rotation orientation, Rect naturalPhysicalDisplay,
6261 int32_t naturalDisplayWidth = DISPLAY_WIDTH,
6262 int32_t naturalDisplayHeight = DISPLAY_HEIGHT) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006263 uint32_t inverseRotationFlags;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006264 auto rotatedWidth = naturalDisplayWidth;
6265 auto rotatedHeight = naturalDisplayHeight;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006266 switch (orientation) {
Michael Wrighta9cf4192022-12-01 23:46:39 +00006267 case ui::ROTATION_90:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006268 inverseRotationFlags = ui::Transform::ROT_270;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006269 std::swap(rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006270 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006271 case ui::ROTATION_180:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006272 inverseRotationFlags = ui::Transform::ROT_180;
6273 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006274 case ui::ROTATION_270:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006275 inverseRotationFlags = ui::Transform::ROT_90;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006276 std::swap(rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006277 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006278 case ui::ROTATION_0:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006279 inverseRotationFlags = ui::Transform::ROT_0;
6280 break;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006281 }
6282
Prabir Pradhana9df3162022-12-05 23:57:27 +00006283 const ui::Transform rotation(inverseRotationFlags, rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006284 const Rect rotatedPhysicalDisplay = rotation.transform(naturalPhysicalDisplay);
6285
6286 std::optional<DisplayViewport> internalViewport =
6287 *mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6288 DisplayViewport& v = *internalViewport;
6289 v.displayId = DISPLAY_ID;
6290 v.orientation = orientation;
6291
6292 v.logicalLeft = 0;
6293 v.logicalTop = 0;
6294 v.logicalRight = 100;
6295 v.logicalBottom = 100;
6296
6297 v.physicalLeft = rotatedPhysicalDisplay.left;
6298 v.physicalTop = rotatedPhysicalDisplay.top;
6299 v.physicalRight = rotatedPhysicalDisplay.right;
6300 v.physicalBottom = rotatedPhysicalDisplay.bottom;
6301
Prabir Pradhana9df3162022-12-05 23:57:27 +00006302 v.deviceWidth = rotatedWidth;
6303 v.deviceHeight = rotatedHeight;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006304
6305 v.isActive = true;
6306 v.uniqueId = UNIQUE_ID;
6307 v.type = ViewportType::INTERNAL;
6308 mFakePolicy->updateViewport(v);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006309 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006310 }
6311
6312 void assertReceivedMove(const Point& point) {
6313 NotifyMotionArgs motionArgs;
6314 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6315 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006316 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Prabir Pradhan5632d622021-09-06 07:57:20 -07006317 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], point.x, point.y,
6318 1, 0, 0, 0, 0, 0, 0, 0));
6319 }
6320};
6321
6322TEST_F(TouchDisplayProjectionTest, IgnoresTouchesOutsidePhysicalDisplay) {
6323 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006324 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006325
6326 prepareButtons();
6327 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006328 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan5632d622021-09-06 07:57:20 -07006329
6330 NotifyMotionArgs motionArgs;
6331
6332 // Configure the DisplayViewport such that the logical display maps to a subsection of
6333 // the display panel called the physical display. Here, the physical display is bounded by the
6334 // points (10, 20) and (70, 160) inside the display space, which is of the size 400 x 800.
6335 static const Rect kPhysicalDisplay{10, 20, 70, 160};
6336 static const std::array<Point, 6> kPointsOutsidePhysicalDisplay{
6337 {{-10, -10}, {0, 0}, {5, 100}, {50, 15}, {75, 100}, {50, 165}}};
6338
Michael Wrighta9cf4192022-12-01 23:46:39 +00006339 for (auto orientation : {ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180, ui::ROTATION_270}) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006340 configurePhysicalDisplay(orientation, kPhysicalDisplay);
6341
6342 // Touches outside the physical display should be ignored, and should not generate any
6343 // events. Ensure touches at the following points that lie outside of the physical display
6344 // area do not generate any events.
6345 for (const auto& point : kPointsOutsidePhysicalDisplay) {
6346 processDown(mapper, toRawX(point.x), toRawY(point.y));
6347 processSync(mapper);
6348 processUp(mapper);
6349 processSync(mapper);
6350 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled())
6351 << "Unexpected event generated for touch outside physical display at point: "
6352 << point.x << ", " << point.y;
6353 }
6354 }
6355}
6356
6357TEST_F(TouchDisplayProjectionTest, EmitsTouchDownAfterEnteringPhysicalDisplay) {
6358 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006359 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006360
6361 prepareButtons();
6362 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006363 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan5632d622021-09-06 07:57:20 -07006364
6365 NotifyMotionArgs motionArgs;
6366
6367 // Configure the DisplayViewport such that the logical display maps to a subsection of
6368 // the display panel called the physical display. Here, the physical display is bounded by the
6369 // points (10, 20) and (70, 160) inside the display space, which is of the size 400 x 800.
6370 static const Rect kPhysicalDisplay{10, 20, 70, 160};
6371
Michael Wrighta9cf4192022-12-01 23:46:39 +00006372 for (auto orientation : {ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180, ui::ROTATION_270}) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006373 configurePhysicalDisplay(orientation, kPhysicalDisplay);
6374
6375 // Touches that start outside the physical display should be ignored until it enters the
6376 // physical display bounds, at which point it should generate a down event. Start a touch at
6377 // the point (5, 100), which is outside the physical display bounds.
6378 static const Point kOutsidePoint{5, 100};
6379 processDown(mapper, toRawX(kOutsidePoint.x), toRawY(kOutsidePoint.y));
6380 processSync(mapper);
6381 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6382
6383 // Move the touch into the physical display area. This should generate a pointer down.
6384 processMove(mapper, toRawX(11), toRawY(21));
6385 processSync(mapper);
6386 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6387 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006388 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Prabir Pradhan5632d622021-09-06 07:57:20 -07006389 ASSERT_NO_FATAL_FAILURE(
6390 assertPointerCoords(motionArgs.pointerCoords[0], 11, 21, 1, 0, 0, 0, 0, 0, 0, 0));
6391
6392 // Move the touch inside the physical display area. This should generate a pointer move.
6393 processMove(mapper, toRawX(69), toRawY(159));
6394 processSync(mapper);
6395 assertReceivedMove({69, 159});
6396
6397 // Move outside the physical display area. Since the pointer is already down, this should
6398 // now continue generating events.
6399 processMove(mapper, toRawX(kOutsidePoint.x), toRawY(kOutsidePoint.y));
6400 processSync(mapper);
6401 assertReceivedMove(kOutsidePoint);
6402
6403 // Release. This should generate a pointer up.
6404 processUp(mapper);
6405 processSync(mapper);
6406 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6407 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
6408 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], kOutsidePoint.x,
6409 kOutsidePoint.y, 1, 0, 0, 0, 0, 0, 0, 0));
6410
6411 // Ensure no more events were generated.
6412 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
6413 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6414 }
6415}
6416
Prabir Pradhana9df3162022-12-05 23:57:27 +00006417// --- TouchscreenPrecisionTests ---
6418
6419// This test suite is used to ensure that touchscreen devices are scaled and configured correctly
6420// in various orientations and with different display rotations. We configure the touchscreen to
6421// have a higher resolution than that of the display by an integer scale factor in each axis so that
6422// we can enforce that coordinates match precisely as expected.
6423class TouchscreenPrecisionTestsFixture : public TouchDisplayProjectionTest,
6424 public ::testing::WithParamInterface<ui::Rotation> {
6425public:
6426 void SetUp() override {
6427 SingleTouchInputMapperTest::SetUp();
6428
6429 // Prepare the raw axes to have twice the resolution of the display in the X axis and
6430 // four times the resolution of the display in the Y axis.
6431 prepareButtons();
6432 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, PRECISION_RAW_X_MIN, PRECISION_RAW_X_MAX,
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006433 PRECISION_RAW_X_FLAT, PRECISION_RAW_X_FUZZ,
6434 PRECISION_RAW_X_RES);
Prabir Pradhana9df3162022-12-05 23:57:27 +00006435 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, PRECISION_RAW_Y_MIN, PRECISION_RAW_Y_MAX,
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006436 PRECISION_RAW_Y_FLAT, PRECISION_RAW_Y_FUZZ,
6437 PRECISION_RAW_Y_RES);
Prabir Pradhana9df3162022-12-05 23:57:27 +00006438 }
6439
6440 static const int32_t PRECISION_RAW_X_MIN = TouchInputMapperTest::RAW_X_MIN;
6441 static const int32_t PRECISION_RAW_X_MAX = PRECISION_RAW_X_MIN + DISPLAY_WIDTH * 2 - 1;
6442 static const int32_t PRECISION_RAW_Y_MIN = TouchInputMapperTest::RAW_Y_MIN;
6443 static const int32_t PRECISION_RAW_Y_MAX = PRECISION_RAW_Y_MIN + DISPLAY_HEIGHT * 4 - 1;
6444
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006445 static const int32_t PRECISION_RAW_X_RES = 50; // units per millimeter
6446 static const int32_t PRECISION_RAW_Y_RES = 100; // units per millimeter
6447
6448 static const int32_t PRECISION_RAW_X_FLAT = 16;
6449 static const int32_t PRECISION_RAW_Y_FLAT = 32;
6450
6451 static const int32_t PRECISION_RAW_X_FUZZ = 4;
6452 static const int32_t PRECISION_RAW_Y_FUZZ = 8;
6453
Prabir Pradhana9df3162022-12-05 23:57:27 +00006454 static const std::array<Point, 4> kRawCorners;
6455};
6456
6457const std::array<Point, 4> TouchscreenPrecisionTestsFixture::kRawCorners = {{
6458 {PRECISION_RAW_X_MIN, PRECISION_RAW_Y_MIN}, // left-top
6459 {PRECISION_RAW_X_MAX, PRECISION_RAW_Y_MIN}, // right-top
6460 {PRECISION_RAW_X_MAX, PRECISION_RAW_Y_MAX}, // right-bottom
6461 {PRECISION_RAW_X_MIN, PRECISION_RAW_Y_MAX}, // left-bottom
6462}};
6463
6464// Tests for how the touchscreen is oriented relative to the natural orientation of the display.
6465// For example, if a touchscreen is configured with an orientation of 90 degrees, it is a portrait
6466// touchscreen panel that is used on a device whose natural display orientation is in landscape.
6467TEST_P(TouchscreenPrecisionTestsFixture, OrientationPrecision) {
6468 enum class Orientation {
6469 ORIENTATION_0 = ui::toRotationInt(ui::ROTATION_0),
6470 ORIENTATION_90 = ui::toRotationInt(ui::ROTATION_90),
6471 ORIENTATION_180 = ui::toRotationInt(ui::ROTATION_180),
6472 ORIENTATION_270 = ui::toRotationInt(ui::ROTATION_270),
6473 ftl_last = ORIENTATION_270,
6474 };
6475 using Orientation::ORIENTATION_0, Orientation::ORIENTATION_90, Orientation::ORIENTATION_180,
6476 Orientation::ORIENTATION_270;
6477 static const std::map<Orientation, std::array<vec2, 4> /*mappedCorners*/> kMappedCorners = {
6478 {ORIENTATION_0, {{{0, 0}, {479.5, 0}, {479.5, 799.75}, {0, 799.75}}}},
6479 {ORIENTATION_90, {{{0, 479.5}, {0, 0}, {799.75, 0}, {799.75, 479.5}}}},
6480 {ORIENTATION_180, {{{479.5, 799.75}, {0, 799.75}, {0, 0}, {479.5, 0}}}},
6481 {ORIENTATION_270, {{{799.75, 0}, {799.75, 479.5}, {0, 479.5}, {0, 0}}}},
6482 };
6483
6484 const auto touchscreenOrientation = static_cast<Orientation>(ui::toRotationInt(GetParam()));
6485
6486 // Configure the touchscreen as being installed in the one of the four different orientations
6487 // relative to the display.
6488 addConfigurationProperty("touch.deviceType", "touchScreen");
6489 addConfigurationProperty("touch.orientation", ftl::enum_string(touchscreenOrientation).c_str());
6490 prepareDisplay(ui::ROTATION_0);
6491
Arpit Singha8c236b2023-04-25 13:56:05 +00006492 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhana9df3162022-12-05 23:57:27 +00006493
6494 // If the touchscreen is installed in a rotated orientation relative to the display (i.e. in
6495 // orientations of either 90 or 270) this means the display's natural resolution will be
6496 // flipped.
6497 const bool displayRotated =
6498 touchscreenOrientation == ORIENTATION_90 || touchscreenOrientation == ORIENTATION_270;
6499 const int32_t width = displayRotated ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
6500 const int32_t height = displayRotated ? DISPLAY_WIDTH : DISPLAY_HEIGHT;
6501 const Rect physicalFrame{0, 0, width, height};
6502 configurePhysicalDisplay(ui::ROTATION_0, physicalFrame, width, height);
6503
6504 const auto& expectedPoints = kMappedCorners.at(touchscreenOrientation);
6505 const float expectedPrecisionX = displayRotated ? 4 : 2;
6506 const float expectedPrecisionY = displayRotated ? 2 : 4;
6507
6508 // Test all four corners.
6509 for (int i = 0; i < 4; i++) {
6510 const auto& raw = kRawCorners[i];
6511 processDown(mapper, raw.x, raw.y);
6512 processSync(mapper);
6513 const auto& expected = expectedPoints[i];
6514 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6515 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6516 WithCoords(expected.x, expected.y),
6517 WithPrecision(expectedPrecisionX, expectedPrecisionY))))
6518 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6519 << "with touchscreen orientation "
6520 << ftl::enum_string(touchscreenOrientation).c_str() << ", expected point ("
6521 << expected.x << ", " << expected.y << ").";
6522 processUp(mapper);
6523 processSync(mapper);
6524 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6525 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6526 WithCoords(expected.x, expected.y))));
6527 }
6528}
6529
Prabir Pradhan82687402022-12-06 01:32:53 +00006530TEST_P(TouchscreenPrecisionTestsFixture, RotationPrecisionWhenOrientationAware) {
6531 static const std::map<ui::Rotation /*rotation*/, std::array<vec2, 4> /*mappedCorners*/>
6532 kMappedCorners = {
6533 {ui::ROTATION_0, {{{0, 0}, {479.5, 0}, {479.5, 799.75}, {0, 799.75}}}},
6534 {ui::ROTATION_90, {{{0.5, 0}, {480, 0}, {480, 799.75}, {0.5, 799.75}}}},
6535 {ui::ROTATION_180, {{{0.5, 0.25}, {480, 0.25}, {480, 800}, {0.5, 800}}}},
6536 {ui::ROTATION_270, {{{0, 0.25}, {479.5, 0.25}, {479.5, 800}, {0, 800}}}},
6537 };
6538
6539 const ui::Rotation displayRotation = GetParam();
6540
6541 addConfigurationProperty("touch.deviceType", "touchScreen");
6542 prepareDisplay(displayRotation);
6543
Arpit Singha8c236b2023-04-25 13:56:05 +00006544 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan82687402022-12-06 01:32:53 +00006545
6546 const auto& expectedPoints = kMappedCorners.at(displayRotation);
6547
6548 // Test all four corners.
6549 for (int i = 0; i < 4; i++) {
6550 const auto& expected = expectedPoints[i];
6551 const auto& raw = kRawCorners[i];
6552 processDown(mapper, raw.x, raw.y);
6553 processSync(mapper);
6554 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6555 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6556 WithCoords(expected.x, expected.y), WithPrecision(2, 4))))
6557 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6558 << "with display rotation " << ui::toCString(displayRotation)
6559 << ", expected point (" << expected.x << ", " << expected.y << ").";
6560 processUp(mapper);
6561 processSync(mapper);
6562 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6563 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6564 WithCoords(expected.x, expected.y))));
6565 }
6566}
6567
Prabir Pradhan3e798762022-12-02 21:02:11 +00006568TEST_P(TouchscreenPrecisionTestsFixture, RotationPrecisionOrientationAwareInOri270) {
6569 static const std::map<ui::Rotation /*orientation*/, std::array<vec2, 4> /*mappedCorners*/>
6570 kMappedCorners = {
6571 {ui::ROTATION_0, {{{799.75, 0}, {799.75, 479.5}, {0, 479.5}, {0, 0}}}},
6572 {ui::ROTATION_90, {{{800, 0}, {800, 479.5}, {0.25, 479.5}, {0.25, 0}}}},
6573 {ui::ROTATION_180, {{{800, 0.5}, {800, 480}, {0.25, 480}, {0.25, 0.5}}}},
6574 {ui::ROTATION_270, {{{799.75, 0.5}, {799.75, 480}, {0, 480}, {0, 0.5}}}},
6575 };
6576
6577 const ui::Rotation displayRotation = GetParam();
6578
6579 addConfigurationProperty("touch.deviceType", "touchScreen");
6580 addConfigurationProperty("touch.orientation", "ORIENTATION_270");
6581
Arpit Singha8c236b2023-04-25 13:56:05 +00006582 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan3e798762022-12-02 21:02:11 +00006583
6584 // Ori 270, so width and height swapped
6585 const Rect physicalFrame{0, 0, DISPLAY_HEIGHT, DISPLAY_WIDTH};
6586 prepareDisplay(displayRotation);
6587 configurePhysicalDisplay(displayRotation, physicalFrame, DISPLAY_HEIGHT, DISPLAY_WIDTH);
6588
6589 const auto& expectedPoints = kMappedCorners.at(displayRotation);
6590
6591 // Test all four corners.
6592 for (int i = 0; i < 4; i++) {
6593 const auto& expected = expectedPoints[i];
6594 const auto& raw = kRawCorners[i];
6595 processDown(mapper, raw.x, raw.y);
6596 processSync(mapper);
6597 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6598 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6599 WithCoords(expected.x, expected.y), WithPrecision(4, 2))))
6600 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6601 << "with display rotation " << ui::toCString(displayRotation)
6602 << ", expected point (" << expected.x << ", " << expected.y << ").";
6603 processUp(mapper);
6604 processSync(mapper);
6605 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6606 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6607 WithCoords(expected.x, expected.y))));
6608 }
6609}
6610
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006611TEST_P(TouchscreenPrecisionTestsFixture, MotionRangesAreOrientedInRotatedDisplay) {
6612 const ui::Rotation displayRotation = GetParam();
6613
6614 addConfigurationProperty("touch.deviceType", "touchScreen");
6615 prepareDisplay(displayRotation);
6616
6617 __attribute__((unused)) SingleTouchInputMapper& mapper =
Arpit Singha8c236b2023-04-25 13:56:05 +00006618 constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006619
6620 const InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
6621 // MotionRanges use display pixels as their units
6622 const auto* xRange = deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHSCREEN);
6623 const auto* yRange = deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_Y, AINPUT_SOURCE_TOUCHSCREEN);
6624
6625 // The MotionRanges should be oriented in the rotated display's coordinate space
6626 const bool displayRotated =
6627 displayRotation == ui::ROTATION_90 || displayRotation == ui::ROTATION_270;
6628
6629 constexpr float MAX_X = 479.5;
6630 constexpr float MAX_Y = 799.75;
6631 EXPECT_EQ(xRange->min, 0.f);
6632 EXPECT_EQ(yRange->min, 0.f);
6633 EXPECT_EQ(xRange->max, displayRotated ? MAX_Y : MAX_X);
6634 EXPECT_EQ(yRange->max, displayRotated ? MAX_X : MAX_Y);
6635
6636 EXPECT_EQ(xRange->flat, 8.f);
6637 EXPECT_EQ(yRange->flat, 8.f);
6638
6639 EXPECT_EQ(xRange->fuzz, 2.f);
6640 EXPECT_EQ(yRange->fuzz, 2.f);
6641
6642 EXPECT_EQ(xRange->resolution, 25.f); // pixels per millimeter
6643 EXPECT_EQ(yRange->resolution, 25.f); // pixels per millimeter
6644}
6645
Prabir Pradhana9df3162022-12-05 23:57:27 +00006646// Run the precision tests for all rotations.
6647INSTANTIATE_TEST_SUITE_P(TouchscreenPrecisionTests, TouchscreenPrecisionTestsFixture,
6648 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
6649 ui::ROTATION_270),
6650 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
6651 return ftl::enum_string(testParamInfo.param);
6652 });
6653
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006654// --- ExternalStylusFusionTest ---
6655
6656class ExternalStylusFusionTest : public SingleTouchInputMapperTest {
6657public:
Prabir Pradhan7ff19a12024-07-29 22:40:31 +00006658 void SetUp() override {
6659 SingleTouchInputMapperTest::SetUp();
6660 mExternalStylusDeviceInfo = {};
6661 mStylusState = {};
6662 }
6663
6664 SingleTouchInputMapper& initializeInputMapperWithExternalStylus(bool supportsPressure = true) {
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006665 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006666 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006667 prepareButtons();
6668 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006669 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006670
Prabir Pradhan7ff19a12024-07-29 22:40:31 +00006671 if (supportsPressure) {
6672 mExternalStylusDeviceInfo.addMotionRange(AMOTION_EVENT_AXIS_PRESSURE,
6673 AINPUT_SOURCE_STYLUS, 0.0f, 1.0f, 0.0f, 0.0f,
6674 0.0f);
6675 mStylusState.pressure = 0.f;
6676 }
6677
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006678 mStylusState.when = ARBITRARY_TIME;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006679 mStylusState.toolType = ToolType::STYLUS;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006680 mReader->getContext()->setExternalStylusDevices({mExternalStylusDeviceInfo});
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006681 configureDevice(InputReaderConfiguration::Change::EXTERNAL_STYLUS_PRESENCE);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006682 processExternalStylusState(mapper);
6683 return mapper;
6684 }
6685
6686 std::list<NotifyArgs> processExternalStylusState(InputMapper& mapper) {
6687 std::list<NotifyArgs> generatedArgs = mapper.updateExternalStylusState(mStylusState);
6688 for (const NotifyArgs& args : generatedArgs) {
6689 mFakeListener->notify(args);
6690 }
6691 // Loop the reader to flush the input listener queue.
6692 mReader->loopOnce();
6693 return generatedArgs;
6694 }
6695
6696protected:
6697 StylusState mStylusState{};
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006698
6699 void testStartFusedStylusGesture(SingleTouchInputMapper& mapper) {
6700 auto toolTypeSource =
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006701 AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006702
6703 // The first pointer is withheld.
6704 processDown(mapper, 100, 200);
6705 processSync(mapper);
6706 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6707 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6708 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6709
6710 // The external stylus reports pressure. The withheld finger pointer is released as a
6711 // stylus.
6712 mStylusState.pressure = 1.f;
6713 processExternalStylusState(mapper);
6714 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6715 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6716 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6717
6718 // Subsequent pointer events are not withheld.
6719 processMove(mapper, 101, 201);
6720 processSync(mapper);
6721 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6722 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6723
6724 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6725 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6726 }
6727
6728 void testSuccessfulFusionGesture(SingleTouchInputMapper& mapper) {
6729 ASSERT_NO_FATAL_FAILURE(testStartFusedStylusGesture(mapper));
6730
6731 // Releasing the touch pointer ends the gesture.
6732 processUp(mapper);
6733 processSync(mapper);
6734 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006735 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(STYLUS_FUSION_SOURCE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006736 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006737
6738 mStylusState.pressure = 0.f;
6739 processExternalStylusState(mapper);
6740 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6741 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6742 }
6743
6744 void testUnsuccessfulFusionGesture(SingleTouchInputMapper& mapper) {
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006745 // When stylus fusion is not successful, events should be reported with the original source.
6746 // In this case, it is from a touchscreen.
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006747 auto toolTypeSource =
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006748 AllOf(WithSource(AINPUT_SOURCE_TOUCHSCREEN), WithToolType(ToolType::FINGER));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006749
6750 // The first pointer is withheld when an external stylus is connected,
6751 // and a timeout is requested.
6752 processDown(mapper, 100, 200);
6753 processSync(mapper);
6754 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6755 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6756 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6757
6758 // If the timeout expires early, it is requested again.
6759 handleTimeout(mapper, ARBITRARY_TIME + 1);
6760 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6761 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6762
6763 // When the timeout expires, the withheld touch is released as a finger pointer.
6764 handleTimeout(mapper, ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT);
6765 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6766 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6767
6768 // Subsequent pointer events are not withheld.
6769 processMove(mapper, 101, 201);
6770 processSync(mapper);
6771 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6772 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6773 processUp(mapper);
6774 processSync(mapper);
6775 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6776 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP))));
6777
6778 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6779 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6780 }
6781
6782private:
6783 InputDeviceInfo mExternalStylusDeviceInfo{};
6784};
6785
Prabir Pradhan7ff19a12024-07-29 22:40:31 +00006786TEST_F(ExternalStylusFusionTest, UsesBluetoothStylusSourceWithPressure) {
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006787 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006788 ASSERT_EQ(STYLUS_FUSION_SOURCE, mapper.getSources());
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006789}
6790
Prabir Pradhan7ff19a12024-07-29 22:40:31 +00006791TEST_F(ExternalStylusFusionTest, DoesNotUseBluetoothStylusSourceWithoutPressure) {
6792 SingleTouchInputMapper& mapper =
6793 initializeInputMapperWithExternalStylus(/*supportsPressure=*/false);
6794 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
6795}
6796
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006797TEST_F(ExternalStylusFusionTest, UnsuccessfulFusion) {
6798 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6799 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6800}
6801
6802TEST_F(ExternalStylusFusionTest, SuccessfulFusion_TouchFirst) {
6803 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6804 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6805}
6806
6807// Test a successful stylus fusion gesture where the pressure is reported by the external
6808// before the touch is reported by the touchscreen.
6809TEST_F(ExternalStylusFusionTest, SuccessfulFusion_PressureFirst) {
6810 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006811 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006812
6813 // The external stylus reports pressure first. It is ignored for now.
6814 mStylusState.pressure = 1.f;
6815 processExternalStylusState(mapper);
6816 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6817 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6818
6819 // When the touch goes down afterwards, it is reported as a stylus pointer.
6820 processDown(mapper, 100, 200);
6821 processSync(mapper);
6822 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6823 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6824 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6825
6826 processMove(mapper, 101, 201);
6827 processSync(mapper);
6828 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6829 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6830 processUp(mapper);
6831 processSync(mapper);
6832 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6833 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP))));
6834
6835 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6836 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6837}
6838
6839TEST_F(ExternalStylusFusionTest, FusionIsRepeatedForEachNewGesture) {
6840 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6841
6842 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6843 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6844
6845 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6846 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6847 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6848 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6849}
6850
6851TEST_F(ExternalStylusFusionTest, FusedPointerReportsPressureChanges) {
6852 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006853 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006854
6855 mStylusState.pressure = 0.8f;
6856 processExternalStylusState(mapper);
6857 processDown(mapper, 100, 200);
6858 processSync(mapper);
6859 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6860 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6861 WithPressure(0.8f))));
6862 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6863
6864 // The external stylus reports a pressure change. We wait for some time for a touch event.
6865 mStylusState.pressure = 0.6f;
6866 processExternalStylusState(mapper);
6867 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6868 ASSERT_NO_FATAL_FAILURE(
6869 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6870
6871 // If a touch is reported within the timeout, it reports the updated pressure.
6872 processMove(mapper, 101, 201);
6873 processSync(mapper);
6874 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6875 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6876 WithPressure(0.6f))));
6877 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6878
6879 // There is another pressure change.
6880 mStylusState.pressure = 0.5f;
6881 processExternalStylusState(mapper);
6882 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6883 ASSERT_NO_FATAL_FAILURE(
6884 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6885
6886 // If a touch is not reported within the timeout, a move event is generated to report
6887 // the new pressure.
6888 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
6889 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6890 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6891 WithPressure(0.5f))));
6892
6893 // If a zero pressure is reported before the touch goes up, the previous pressure value is
6894 // repeated indefinitely.
6895 mStylusState.pressure = 0.0f;
6896 processExternalStylusState(mapper);
6897 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6898 ASSERT_NO_FATAL_FAILURE(
6899 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6900 processMove(mapper, 102, 202);
6901 processSync(mapper);
6902 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6903 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6904 WithPressure(0.5f))));
6905 processMove(mapper, 103, 203);
6906 processSync(mapper);
6907 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6908 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6909 WithPressure(0.5f))));
6910
6911 processUp(mapper);
6912 processSync(mapper);
6913 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006914 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(STYLUS_FUSION_SOURCE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006915 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006916
6917 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6918 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6919}
6920
6921TEST_F(ExternalStylusFusionTest, FusedPointerReportsToolTypeChanges) {
6922 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006923 auto source = WithSource(STYLUS_FUSION_SOURCE);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006924
6925 mStylusState.pressure = 1.f;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006926 mStylusState.toolType = ToolType::ERASER;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006927 processExternalStylusState(mapper);
6928 processDown(mapper, 100, 200);
6929 processSync(mapper);
6930 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6931 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006932 WithToolType(ToolType::ERASER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006933 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6934
6935 // The external stylus reports a tool change. We wait for some time for a touch event.
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006936 mStylusState.toolType = ToolType::STYLUS;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006937 processExternalStylusState(mapper);
6938 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6939 ASSERT_NO_FATAL_FAILURE(
6940 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6941
6942 // If a touch is reported within the timeout, it reports the updated pressure.
6943 processMove(mapper, 101, 201);
6944 processSync(mapper);
6945 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6946 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006947 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006948 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6949
6950 // There is another tool type change.
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006951 mStylusState.toolType = ToolType::FINGER;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006952 processExternalStylusState(mapper);
6953 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6954 ASSERT_NO_FATAL_FAILURE(
6955 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6956
6957 // If a touch is not reported within the timeout, a move event is generated to report
6958 // the new tool type.
6959 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
6960 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6961 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006962 WithToolType(ToolType::FINGER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006963
6964 processUp(mapper);
6965 processSync(mapper);
6966 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6967 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006968 WithToolType(ToolType::FINGER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006969
6970 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6971 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6972}
6973
6974TEST_F(ExternalStylusFusionTest, FusedPointerReportsButtons) {
6975 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006976 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006977
6978 ASSERT_NO_FATAL_FAILURE(testStartFusedStylusGesture(mapper));
6979
6980 // The external stylus reports a button change. We wait for some time for a touch event.
6981 mStylusState.buttons = AMOTION_EVENT_BUTTON_STYLUS_PRIMARY;
6982 processExternalStylusState(mapper);
6983 ASSERT_NO_FATAL_FAILURE(
6984 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6985
6986 // If a touch is reported within the timeout, it reports the updated button state.
6987 processMove(mapper, 101, 201);
6988 processSync(mapper);
6989 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6990 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6991 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6992 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6993 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
6994 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6995 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6996
6997 // The button is now released.
6998 mStylusState.buttons = 0;
6999 processExternalStylusState(mapper);
7000 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7001 ASSERT_NO_FATAL_FAILURE(
7002 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7003
7004 // If a touch is not reported within the timeout, a move event is generated to report
7005 // the new button state.
7006 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007007 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7008 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
7009 WithButtonState(0))));
7010 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhan124ea442022-10-28 20:27:44 +00007011 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
7012 WithButtonState(0))));
7013
7014 processUp(mapper);
7015 processSync(mapper);
7016 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007017 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
7018
7019 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7020 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7021}
7022
Michael Wrightd02c5b62014-02-10 15:10:22 -08007023// --- MultiTouchInputMapperTest ---
7024
7025class MultiTouchInputMapperTest : public TouchInputMapperTest {
7026protected:
7027 void prepareAxes(int axes);
7028
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007029 void processPosition(MultiTouchInputMapper& mapper, int32_t x, int32_t y);
7030 void processTouchMajor(MultiTouchInputMapper& mapper, int32_t touchMajor);
7031 void processTouchMinor(MultiTouchInputMapper& mapper, int32_t touchMinor);
7032 void processToolMajor(MultiTouchInputMapper& mapper, int32_t toolMajor);
7033 void processToolMinor(MultiTouchInputMapper& mapper, int32_t toolMinor);
7034 void processOrientation(MultiTouchInputMapper& mapper, int32_t orientation);
7035 void processPressure(MultiTouchInputMapper& mapper, int32_t pressure);
7036 void processDistance(MultiTouchInputMapper& mapper, int32_t distance);
7037 void processId(MultiTouchInputMapper& mapper, int32_t id);
7038 void processSlot(MultiTouchInputMapper& mapper, int32_t slot);
7039 void processToolType(MultiTouchInputMapper& mapper, int32_t toolType);
7040 void processKey(MultiTouchInputMapper& mapper, int32_t code, int32_t value);
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00007041 void processHidUsage(MultiTouchInputMapper& mapper, int32_t usageCode, int32_t value);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007042 void processMTSync(MultiTouchInputMapper& mapper);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00007043 void processSync(MultiTouchInputMapper& mapper, nsecs_t eventTime = ARBITRARY_TIME,
7044 nsecs_t readTime = READ_TIME);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007045};
7046
7047void MultiTouchInputMapperTest::prepareAxes(int axes) {
7048 if (axes & POSITION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007049 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
7050 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007051 }
7052 if (axes & TOUCH) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007053 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN,
7054 RAW_TOUCH_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007055 if (axes & MINOR) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007056 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN,
7057 RAW_TOUCH_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007058 }
7059 }
7060 if (axes & TOOL) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007061 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7062 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007063 if (axes & MINOR) {
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007064 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MIN,
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007065 RAW_TOOL_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007066 }
7067 }
7068 if (axes & ORIENTATION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007069 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_ORIENTATION, RAW_ORIENTATION_MIN,
7070 RAW_ORIENTATION_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007071 }
7072 if (axes & PRESSURE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007073 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_PRESSURE, RAW_PRESSURE_MIN,
7074 RAW_PRESSURE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007075 }
7076 if (axes & DISTANCE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007077 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_DISTANCE, RAW_DISTANCE_MIN,
7078 RAW_DISTANCE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007079 }
7080 if (axes & ID) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007081 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TRACKING_ID, RAW_ID_MIN, RAW_ID_MAX, 0,
7082 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007083 }
7084 if (axes & SLOT) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007085 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_SLOT, RAW_SLOT_MIN, RAW_SLOT_MAX, 0, 0);
7086 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007087 }
7088 if (axes & TOOL_TYPE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007089 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007090 }
7091}
7092
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007093void MultiTouchInputMapperTest::processPosition(MultiTouchInputMapper& mapper, int32_t x,
7094 int32_t y) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007095 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
7096 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007097}
7098
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007099void MultiTouchInputMapperTest::processTouchMajor(MultiTouchInputMapper& mapper,
7100 int32_t touchMajor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007101 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOUCH_MAJOR, touchMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007102}
7103
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007104void MultiTouchInputMapperTest::processTouchMinor(MultiTouchInputMapper& mapper,
7105 int32_t touchMinor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007106 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOUCH_MINOR, touchMinor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007107}
7108
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007109void MultiTouchInputMapperTest::processToolMajor(MultiTouchInputMapper& mapper, int32_t toolMajor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007110 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_WIDTH_MAJOR, toolMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007111}
7112
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007113void MultiTouchInputMapperTest::processToolMinor(MultiTouchInputMapper& mapper, int32_t toolMinor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007114 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_WIDTH_MINOR, toolMinor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007115}
7116
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007117void MultiTouchInputMapperTest::processOrientation(MultiTouchInputMapper& mapper,
7118 int32_t orientation) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007119 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_ORIENTATION, orientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007120}
7121
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007122void MultiTouchInputMapperTest::processPressure(MultiTouchInputMapper& mapper, int32_t pressure) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007123 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_PRESSURE, pressure);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007124}
7125
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007126void MultiTouchInputMapperTest::processDistance(MultiTouchInputMapper& mapper, int32_t distance) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007127 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_DISTANCE, distance);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007128}
7129
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007130void MultiTouchInputMapperTest::processId(MultiTouchInputMapper& mapper, int32_t id) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007131 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TRACKING_ID, id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007132}
7133
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007134void MultiTouchInputMapperTest::processSlot(MultiTouchInputMapper& mapper, int32_t slot) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007135 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_SLOT, slot);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007136}
7137
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007138void MultiTouchInputMapperTest::processToolType(MultiTouchInputMapper& mapper, int32_t toolType) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007139 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOOL_TYPE, toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007140}
7141
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007142void MultiTouchInputMapperTest::processKey(MultiTouchInputMapper& mapper, int32_t code,
7143 int32_t value) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007144 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007145}
7146
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00007147void MultiTouchInputMapperTest::processHidUsage(MultiTouchInputMapper& mapper, int32_t usageCode,
7148 int32_t value) {
7149 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, usageCode);
7150 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, value);
7151}
7152
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007153void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper& mapper) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007154 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_MT_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007155}
7156
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00007157void MultiTouchInputMapperTest::processSync(MultiTouchInputMapper& mapper, nsecs_t eventTime,
7158 nsecs_t readTime) {
7159 process(mapper, eventTime, readTime, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007160}
7161
Michael Wrightd02c5b62014-02-10 15:10:22 -08007162TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackingIds) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007163 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007164 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007165 prepareAxes(POSITION);
7166 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007167 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007168
arthurhungdcef2dc2020-08-11 14:47:50 +08007169 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007170
7171 NotifyMotionArgs motionArgs;
7172
7173 // Two fingers down at once.
7174 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7175 processPosition(mapper, x1, y1);
7176 processMTSync(mapper);
7177 processPosition(mapper, x2, y2);
7178 processMTSync(mapper);
7179 processSync(mapper);
7180
7181 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7182 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7183 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7184 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7185 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7186 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
7187 ASSERT_EQ(0, motionArgs.flags);
7188 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7189 ASSERT_EQ(0, motionArgs.buttonState);
7190 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007191 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007192 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007193 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007194 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7195 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7196 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7197 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7198 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7199
7200 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7201 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7202 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7203 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7204 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007205 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007206 ASSERT_EQ(0, motionArgs.flags);
7207 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7208 ASSERT_EQ(0, motionArgs.buttonState);
7209 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007210 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007211 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007212 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007213 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007214 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007215 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7216 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7217 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7218 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7219 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7220 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7221 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7222
7223 // Move.
7224 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7225 processPosition(mapper, x1, y1);
7226 processMTSync(mapper);
7227 processPosition(mapper, x2, y2);
7228 processMTSync(mapper);
7229 processSync(mapper);
7230
7231 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7232 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7233 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7234 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7235 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7236 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7237 ASSERT_EQ(0, motionArgs.flags);
7238 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7239 ASSERT_EQ(0, motionArgs.buttonState);
7240 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007241 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007242 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007243 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007244 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007245 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007246 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7247 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7248 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7249 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7250 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7251 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7252 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7253
7254 // First finger up.
7255 x2 += 15; y2 -= 20;
7256 processPosition(mapper, x2, y2);
7257 processMTSync(mapper);
7258 processSync(mapper);
7259
7260 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7261 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7262 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7263 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7264 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007265 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007266 ASSERT_EQ(0, motionArgs.flags);
7267 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7268 ASSERT_EQ(0, motionArgs.buttonState);
7269 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007270 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007271 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007272 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007273 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007274 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007275 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7276 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7277 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7278 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7279 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7280 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7281 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7282
7283 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7284 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7285 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7286 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7287 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7288 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7289 ASSERT_EQ(0, motionArgs.flags);
7290 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7291 ASSERT_EQ(0, motionArgs.buttonState);
7292 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007293 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007294 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007295 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007296 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7297 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7298 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7299 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7300 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7301
7302 // Move.
7303 x2 += 20; y2 -= 25;
7304 processPosition(mapper, x2, y2);
7305 processMTSync(mapper);
7306 processSync(mapper);
7307
7308 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7309 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7310 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7311 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7312 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7313 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7314 ASSERT_EQ(0, motionArgs.flags);
7315 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7316 ASSERT_EQ(0, motionArgs.buttonState);
7317 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007318 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007319 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007320 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007321 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7322 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7323 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7324 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7325 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7326
7327 // New finger down.
7328 int32_t x3 = 700, y3 = 300;
7329 processPosition(mapper, x2, y2);
7330 processMTSync(mapper);
7331 processPosition(mapper, x3, y3);
7332 processMTSync(mapper);
7333 processSync(mapper);
7334
7335 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7336 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7337 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7338 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7339 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007340 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007341 ASSERT_EQ(0, motionArgs.flags);
7342 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7343 ASSERT_EQ(0, motionArgs.buttonState);
7344 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007345 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007346 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007347 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007348 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007349 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007350 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7351 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7352 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7353 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7354 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7355 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7356 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7357
7358 // Second finger up.
7359 x3 += 30; y3 -= 20;
7360 processPosition(mapper, x3, y3);
7361 processMTSync(mapper);
7362 processSync(mapper);
7363
7364 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7365 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7366 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7367 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7368 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007369 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007370 ASSERT_EQ(0, motionArgs.flags);
7371 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7372 ASSERT_EQ(0, motionArgs.buttonState);
7373 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007374 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007375 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007376 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007377 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007378 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007379 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7380 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7381 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7382 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7383 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7384 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7385 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7386
7387 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7388 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7389 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7390 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7391 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7392 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7393 ASSERT_EQ(0, motionArgs.flags);
7394 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7395 ASSERT_EQ(0, motionArgs.buttonState);
7396 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007397 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007398 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007399 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007400 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7401 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7402 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7403 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7404 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7405
7406 // Last finger up.
7407 processMTSync(mapper);
7408 processSync(mapper);
7409
7410 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7411 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7412 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7413 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7414 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7415 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
7416 ASSERT_EQ(0, motionArgs.flags);
7417 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7418 ASSERT_EQ(0, motionArgs.buttonState);
7419 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007420 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007421 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007422 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007423 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7424 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7425 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7426 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7427 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7428
7429 // Should not have sent any more keys or motions.
7430 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7431 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7432}
7433
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007434TEST_F(MultiTouchInputMapperTest, AxisResolution_IsPopulated) {
7435 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007436 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007437
7438 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, /*flat*/ 0,
7439 /*fuzz*/ 0, /*resolution*/ 10);
7440 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, /*flat*/ 0,
7441 /*fuzz*/ 0, /*resolution*/ 11);
7442 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX,
7443 /*flat*/ 0, /*fuzz*/ 0, /*resolution*/ 12);
7444 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX,
7445 /*flat*/ 0, /*fuzz*/ 0, /*resolution*/ 13);
7446 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7447 /*flat*/ 0, /*flat*/ 0, /*resolution*/ 14);
7448 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7449 /*flat*/ 0, /*flat*/ 0, /*resolution*/ 15);
7450
Arpit Singha8c236b2023-04-25 13:56:05 +00007451 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007452
7453 // X and Y axes
7454 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_X, 10 / X_PRECISION);
7455 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_Y, 11 / Y_PRECISION);
7456 // Touch major and minor
7457 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOUCH_MAJOR, 12 * GEOMETRIC_SCALE);
7458 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOUCH_MINOR, 13 * GEOMETRIC_SCALE);
7459 // Tool major and minor
7460 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOOL_MAJOR, 14 * GEOMETRIC_SCALE);
7461 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOOL_MINOR, 15 * GEOMETRIC_SCALE);
7462}
7463
7464TEST_F(MultiTouchInputMapperTest, TouchMajorAndMinorAxes_DoNotAppearIfNotSupported) {
7465 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007466 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007467
7468 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, /*flat*/ 0,
7469 /*fuzz*/ 0, /*resolution*/ 10);
7470 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, /*flat*/ 0,
7471 /*fuzz*/ 0, /*resolution*/ 11);
7472
7473 // We do not add ABS_MT_TOUCH_MAJOR / MINOR or ABS_MT_WIDTH_MAJOR / MINOR axes
7474
Arpit Singha8c236b2023-04-25 13:56:05 +00007475 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007476
7477 // Touch major and minor
7478 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOUCH_MAJOR);
7479 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOUCH_MINOR);
7480 // Tool major and minor
7481 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOOL_MAJOR);
7482 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOOL_MINOR);
7483}
7484
Michael Wrightd02c5b62014-02-10 15:10:22 -08007485TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingIds) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007486 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007487 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007488 prepareAxes(POSITION | ID);
7489 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007490 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007491
arthurhungdcef2dc2020-08-11 14:47:50 +08007492 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007493
7494 NotifyMotionArgs motionArgs;
7495
7496 // Two fingers down at once.
7497 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7498 processPosition(mapper, x1, y1);
7499 processId(mapper, 1);
7500 processMTSync(mapper);
7501 processPosition(mapper, x2, y2);
7502 processId(mapper, 2);
7503 processMTSync(mapper);
7504 processSync(mapper);
7505
7506 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7507 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007508 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007509 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007510 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007511 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7512 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7513
7514 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007515 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007516 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007517 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007518 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007519 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007520 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007521 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7522 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7523 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7524 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7525
7526 // Move.
7527 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7528 processPosition(mapper, x1, y1);
7529 processId(mapper, 1);
7530 processMTSync(mapper);
7531 processPosition(mapper, x2, y2);
7532 processId(mapper, 2);
7533 processMTSync(mapper);
7534 processSync(mapper);
7535
7536 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7537 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007538 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007539 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007540 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007541 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007542 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007543 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7544 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7545 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7546 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7547
7548 // First finger up.
7549 x2 += 15; y2 -= 20;
7550 processPosition(mapper, x2, y2);
7551 processId(mapper, 2);
7552 processMTSync(mapper);
7553 processSync(mapper);
7554
7555 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007556 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007557 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007558 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007559 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007560 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007561 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007562 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7563 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7564 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7565 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7566
7567 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7568 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007569 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007570 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007571 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007572 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7573 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7574
7575 // Move.
7576 x2 += 20; y2 -= 25;
7577 processPosition(mapper, x2, y2);
7578 processId(mapper, 2);
7579 processMTSync(mapper);
7580 processSync(mapper);
7581
7582 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7583 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007584 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007585 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007586 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007587 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7588 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7589
7590 // New finger down.
7591 int32_t x3 = 700, y3 = 300;
7592 processPosition(mapper, x2, y2);
7593 processId(mapper, 2);
7594 processMTSync(mapper);
7595 processPosition(mapper, x3, y3);
7596 processId(mapper, 3);
7597 processMTSync(mapper);
7598 processSync(mapper);
7599
7600 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007601 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007602 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007603 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007604 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007605 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007606 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007607 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7608 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7609 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7610 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7611
7612 // Second finger up.
7613 x3 += 30; y3 -= 20;
7614 processPosition(mapper, x3, y3);
7615 processId(mapper, 3);
7616 processMTSync(mapper);
7617 processSync(mapper);
7618
7619 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007620 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007621 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007622 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007623 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007624 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007625 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007626 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7627 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7628 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7629 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7630
7631 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7632 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007633 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007634 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007635 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007636 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7637 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7638
7639 // Last finger up.
7640 processMTSync(mapper);
7641 processSync(mapper);
7642
7643 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7644 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007645 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007646 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007647 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007648 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7649 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7650
7651 // Should not have sent any more keys or motions.
7652 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7653 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7654}
7655
7656TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithSlots) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007657 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007658 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007659 prepareAxes(POSITION | ID | SLOT);
7660 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007661 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007662
arthurhungdcef2dc2020-08-11 14:47:50 +08007663 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007664
7665 NotifyMotionArgs motionArgs;
7666
7667 // Two fingers down at once.
7668 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7669 processPosition(mapper, x1, y1);
7670 processId(mapper, 1);
7671 processSlot(mapper, 1);
7672 processPosition(mapper, x2, y2);
7673 processId(mapper, 2);
7674 processSync(mapper);
7675
7676 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7677 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007678 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007679 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007680 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007681 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7682 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7683
7684 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007685 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007686 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007687 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007688 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007689 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007690 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007691 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7692 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7693 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7694 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7695
7696 // Move.
7697 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7698 processSlot(mapper, 0);
7699 processPosition(mapper, x1, y1);
7700 processSlot(mapper, 1);
7701 processPosition(mapper, x2, y2);
7702 processSync(mapper);
7703
7704 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7705 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, 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 // First finger up.
7717 x2 += 15; y2 -= 20;
7718 processSlot(mapper, 0);
7719 processId(mapper, -1);
7720 processSlot(mapper, 1);
7721 processPosition(mapper, x2, y2);
7722 processSync(mapper);
7723
7724 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007725 ASSERT_EQ(ACTION_POINTER_0_UP, 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 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7737 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007738 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007739 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007740 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007741 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7742 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7743
7744 // Move.
7745 x2 += 20; y2 -= 25;
7746 processPosition(mapper, x2, y2);
7747 processSync(mapper);
7748
7749 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7750 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007751 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007752 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007753 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007754 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7755 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7756
7757 // New finger down.
7758 int32_t x3 = 700, y3 = 300;
7759 processPosition(mapper, x2, y2);
7760 processSlot(mapper, 0);
7761 processId(mapper, 3);
7762 processPosition(mapper, x3, y3);
7763 processSync(mapper);
7764
7765 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007766 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007767 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007768 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007769 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007770 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007771 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007772 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7773 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7774 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7775 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7776
7777 // Second finger up.
7778 x3 += 30; y3 -= 20;
7779 processSlot(mapper, 1);
7780 processId(mapper, -1);
7781 processSlot(mapper, 0);
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_1_UP, 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 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7798 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007799 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007800 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007801 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007802 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7803 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7804
7805 // Last finger up.
7806 processId(mapper, -1);
7807 processSync(mapper);
7808
7809 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7810 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007811 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007812 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007813 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007814 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7815 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7816
7817 // Should not have sent any more keys or motions.
7818 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7819 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7820}
7821
7822TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007823 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007824 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007825 prepareAxes(POSITION | TOUCH | TOOL | PRESSURE | ORIENTATION | ID | MINOR | DISTANCE);
Arpit Singha8c236b2023-04-25 13:56:05 +00007826 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007827
7828 // These calculations are based on the input device calibration documentation.
7829 int32_t rawX = 100;
7830 int32_t rawY = 200;
7831 int32_t rawTouchMajor = 7;
7832 int32_t rawTouchMinor = 6;
7833 int32_t rawToolMajor = 9;
7834 int32_t rawToolMinor = 8;
7835 int32_t rawPressure = 11;
7836 int32_t rawDistance = 0;
7837 int32_t rawOrientation = 3;
7838 int32_t id = 5;
7839
7840 float x = toDisplayX(rawX);
7841 float y = toDisplayY(rawY);
7842 float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
7843 float size = avg(rawTouchMajor, rawTouchMinor) / RAW_TOUCH_MAX;
7844 float toolMajor = float(rawToolMajor) * GEOMETRIC_SCALE;
7845 float toolMinor = float(rawToolMinor) * GEOMETRIC_SCALE;
7846 float touchMajor = float(rawTouchMajor) * GEOMETRIC_SCALE;
7847 float touchMinor = float(rawTouchMinor) * GEOMETRIC_SCALE;
7848 float orientation = float(rawOrientation) / RAW_ORIENTATION_MAX * M_PI_2;
7849 float distance = float(rawDistance);
7850
7851 processPosition(mapper, rawX, rawY);
7852 processTouchMajor(mapper, rawTouchMajor);
7853 processTouchMinor(mapper, rawTouchMinor);
7854 processToolMajor(mapper, rawToolMajor);
7855 processToolMinor(mapper, rawToolMinor);
7856 processPressure(mapper, rawPressure);
7857 processOrientation(mapper, rawOrientation);
7858 processDistance(mapper, rawDistance);
7859 processId(mapper, id);
7860 processMTSync(mapper);
7861 processSync(mapper);
7862
7863 NotifyMotionArgs args;
7864 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7865 ASSERT_EQ(0, args.pointerProperties[0].id);
7866 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7867 x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor,
7868 orientation, distance));
Prabir Pradhan9a53b552024-06-04 02:59:40 +00007869 ASSERT_EQ(args.flags, AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007870}
7871
7872TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_GeometricCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007873 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007874 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007875 prepareAxes(POSITION | TOUCH | TOOL | MINOR);
7876 addConfigurationProperty("touch.size.calibration", "geometric");
Arpit Singha8c236b2023-04-25 13:56:05 +00007877 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007878
7879 // These calculations are based on the input device calibration documentation.
7880 int32_t rawX = 100;
7881 int32_t rawY = 200;
7882 int32_t rawTouchMajor = 140;
7883 int32_t rawTouchMinor = 120;
7884 int32_t rawToolMajor = 180;
7885 int32_t rawToolMinor = 160;
7886
7887 float x = toDisplayX(rawX);
7888 float y = toDisplayY(rawY);
7889 float size = avg(rawTouchMajor, rawTouchMinor) / RAW_TOUCH_MAX;
7890 float toolMajor = float(rawToolMajor) * GEOMETRIC_SCALE;
7891 float toolMinor = float(rawToolMinor) * GEOMETRIC_SCALE;
7892 float touchMajor = float(rawTouchMajor) * GEOMETRIC_SCALE;
7893 float touchMinor = float(rawTouchMinor) * GEOMETRIC_SCALE;
7894
7895 processPosition(mapper, rawX, rawY);
7896 processTouchMajor(mapper, rawTouchMajor);
7897 processTouchMinor(mapper, rawTouchMinor);
7898 processToolMajor(mapper, rawToolMajor);
7899 processToolMinor(mapper, rawToolMinor);
7900 processMTSync(mapper);
7901 processSync(mapper);
7902
7903 NotifyMotionArgs args;
7904 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7905 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7906 x, y, 1.0f, size, touchMajor, touchMinor, toolMajor, toolMinor, 0, 0));
7907}
7908
7909TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_SummedLinearCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007910 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007911 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007912 prepareAxes(POSITION | TOUCH | TOOL);
7913 addConfigurationProperty("touch.size.calibration", "diameter");
7914 addConfigurationProperty("touch.size.scale", "10");
7915 addConfigurationProperty("touch.size.bias", "160");
7916 addConfigurationProperty("touch.size.isSummed", "1");
Arpit Singha8c236b2023-04-25 13:56:05 +00007917 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007918
7919 // These calculations are based on the input device calibration documentation.
7920 // Note: We only provide a single common touch/tool value because the device is assumed
7921 // not to emit separate values for each pointer (isSummed = 1).
7922 int32_t rawX = 100;
7923 int32_t rawY = 200;
7924 int32_t rawX2 = 150;
7925 int32_t rawY2 = 250;
7926 int32_t rawTouchMajor = 5;
7927 int32_t rawToolMajor = 8;
7928
7929 float x = toDisplayX(rawX);
7930 float y = toDisplayY(rawY);
7931 float x2 = toDisplayX(rawX2);
7932 float y2 = toDisplayY(rawY2);
7933 float size = float(rawTouchMajor) / 2 / RAW_TOUCH_MAX;
7934 float touch = float(rawTouchMajor) / 2 * 10.0f + 160.0f;
7935 float tool = float(rawToolMajor) / 2 * 10.0f + 160.0f;
7936
7937 processPosition(mapper, rawX, rawY);
7938 processTouchMajor(mapper, rawTouchMajor);
7939 processToolMajor(mapper, rawToolMajor);
7940 processMTSync(mapper);
7941 processPosition(mapper, rawX2, rawY2);
7942 processTouchMajor(mapper, rawTouchMajor);
7943 processToolMajor(mapper, rawToolMajor);
7944 processMTSync(mapper);
7945 processSync(mapper);
7946
7947 NotifyMotionArgs args;
7948 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7949 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
7950
7951 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007952 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007953 ASSERT_EQ(size_t(2), args.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007954 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7955 x, y, 1.0f, size, touch, touch, tool, tool, 0, 0));
7956 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[1],
7957 x2, y2, 1.0f, size, touch, touch, tool, tool, 0, 0));
7958}
7959
7960TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_AreaCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007961 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007962 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007963 prepareAxes(POSITION | TOUCH | TOOL);
7964 addConfigurationProperty("touch.size.calibration", "area");
7965 addConfigurationProperty("touch.size.scale", "43");
7966 addConfigurationProperty("touch.size.bias", "3");
Arpit Singha8c236b2023-04-25 13:56:05 +00007967 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007968
7969 // These calculations are based on the input device calibration documentation.
7970 int32_t rawX = 100;
7971 int32_t rawY = 200;
7972 int32_t rawTouchMajor = 5;
7973 int32_t rawToolMajor = 8;
7974
7975 float x = toDisplayX(rawX);
7976 float y = toDisplayY(rawY);
7977 float size = float(rawTouchMajor) / RAW_TOUCH_MAX;
7978 float touch = sqrtf(rawTouchMajor) * 43.0f + 3.0f;
7979 float tool = sqrtf(rawToolMajor) * 43.0f + 3.0f;
7980
7981 processPosition(mapper, rawX, rawY);
7982 processTouchMajor(mapper, rawTouchMajor);
7983 processToolMajor(mapper, rawToolMajor);
7984 processMTSync(mapper);
7985 processSync(mapper);
7986
7987 NotifyMotionArgs args;
7988 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7989 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7990 x, y, 1.0f, size, touch, touch, tool, tool, 0, 0));
7991}
7992
7993TEST_F(MultiTouchInputMapperTest, Process_PressureAxis_AmplitudeCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007994 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007995 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007996 prepareAxes(POSITION | PRESSURE);
7997 addConfigurationProperty("touch.pressure.calibration", "amplitude");
7998 addConfigurationProperty("touch.pressure.scale", "0.01");
Arpit Singha8c236b2023-04-25 13:56:05 +00007999 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008000
Michael Wrightaa449c92017-12-13 21:21:43 +00008001 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +00008002 mapper.populateDeviceInfo(info);
Michael Wrightaa449c92017-12-13 21:21:43 +00008003 ASSERT_NO_FATAL_FAILURE(assertMotionRange(info,
8004 AINPUT_MOTION_RANGE_PRESSURE, AINPUT_SOURCE_TOUCHSCREEN,
8005 0.0f, RAW_PRESSURE_MAX * 0.01, 0.0f, 0.0f));
8006
Michael Wrightd02c5b62014-02-10 15:10:22 -08008007 // These calculations are based on the input device calibration documentation.
8008 int32_t rawX = 100;
8009 int32_t rawY = 200;
8010 int32_t rawPressure = 60;
8011
8012 float x = toDisplayX(rawX);
8013 float y = toDisplayY(rawY);
8014 float pressure = float(rawPressure) * 0.01f;
8015
8016 processPosition(mapper, rawX, rawY);
8017 processPressure(mapper, rawPressure);
8018 processMTSync(mapper);
8019 processSync(mapper);
8020
8021 NotifyMotionArgs args;
8022 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8023 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8024 x, y, pressure, 0, 0, 0, 0, 0, 0, 0));
8025}
8026
8027TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllButtons) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008028 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008029 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008030 prepareAxes(POSITION | ID | SLOT);
Arpit Singha8c236b2023-04-25 13:56:05 +00008031 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008032
8033 NotifyMotionArgs motionArgs;
8034 NotifyKeyArgs keyArgs;
8035
8036 processId(mapper, 1);
8037 processPosition(mapper, 100, 200);
8038 processSync(mapper);
8039 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8040 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8041 ASSERT_EQ(0, motionArgs.buttonState);
8042
8043 // press BTN_LEFT, release BTN_LEFT
8044 processKey(mapper, BTN_LEFT, 1);
8045 processSync(mapper);
8046 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8047 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
8048 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
8049
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008050 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8051 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8052 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
8053
Michael Wrightd02c5b62014-02-10 15:10:22 -08008054 processKey(mapper, BTN_LEFT, 0);
8055 processSync(mapper);
8056 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008057 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008058 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008059
8060 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008061 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008062 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008063
8064 // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
8065 processKey(mapper, BTN_RIGHT, 1);
8066 processKey(mapper, BTN_MIDDLE, 1);
8067 processSync(mapper);
8068 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8069 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
8070 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
8071 motionArgs.buttonState);
8072
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008073 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8074 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8075 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
8076
8077 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8078 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8079 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
8080 motionArgs.buttonState);
8081
Michael Wrightd02c5b62014-02-10 15:10:22 -08008082 processKey(mapper, BTN_RIGHT, 0);
8083 processSync(mapper);
8084 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008085 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008086 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008087
8088 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008089 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008090 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008091
8092 processKey(mapper, BTN_MIDDLE, 0);
8093 processSync(mapper);
8094 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008095 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008096 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008097
8098 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008099 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008100 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008101
8102 // press BTN_BACK, release BTN_BACK
8103 processKey(mapper, BTN_BACK, 1);
8104 processSync(mapper);
8105 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8106 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8107 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008108
Michael Wrightd02c5b62014-02-10 15:10:22 -08008109 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008110 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008111 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
8112
8113 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8114 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8115 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008116
8117 processKey(mapper, BTN_BACK, 0);
8118 processSync(mapper);
8119 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008120 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008121 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008122
8123 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008124 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008125 ASSERT_EQ(0, motionArgs.buttonState);
8126
Michael Wrightd02c5b62014-02-10 15:10:22 -08008127 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8128 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8129 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
8130
8131 // press BTN_SIDE, release BTN_SIDE
8132 processKey(mapper, BTN_SIDE, 1);
8133 processSync(mapper);
8134 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8135 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8136 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008137
Michael Wrightd02c5b62014-02-10 15:10:22 -08008138 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008139 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008140 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
8141
8142 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8143 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8144 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008145
8146 processKey(mapper, BTN_SIDE, 0);
8147 processSync(mapper);
8148 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008149 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008150 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008151
8152 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008153 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008154 ASSERT_EQ(0, motionArgs.buttonState);
8155
Michael Wrightd02c5b62014-02-10 15:10:22 -08008156 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8157 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8158 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
8159
8160 // press BTN_FORWARD, release BTN_FORWARD
8161 processKey(mapper, BTN_FORWARD, 1);
8162 processSync(mapper);
8163 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8164 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8165 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008166
Michael Wrightd02c5b62014-02-10 15:10:22 -08008167 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008168 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008169 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
8170
8171 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8172 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8173 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008174
8175 processKey(mapper, BTN_FORWARD, 0);
8176 processSync(mapper);
8177 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008178 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008179 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008180
8181 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008182 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008183 ASSERT_EQ(0, motionArgs.buttonState);
8184
Michael Wrightd02c5b62014-02-10 15:10:22 -08008185 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8186 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8187 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
8188
8189 // press BTN_EXTRA, release BTN_EXTRA
8190 processKey(mapper, BTN_EXTRA, 1);
8191 processSync(mapper);
8192 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8193 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8194 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008195
Michael Wrightd02c5b62014-02-10 15:10:22 -08008196 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008197 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008198 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
8199
8200 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8201 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8202 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008203
8204 processKey(mapper, BTN_EXTRA, 0);
8205 processSync(mapper);
8206 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008207 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008208 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008209
8210 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008211 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008212 ASSERT_EQ(0, motionArgs.buttonState);
8213
Michael Wrightd02c5b62014-02-10 15:10:22 -08008214 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8215 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8216 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
8217
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008218 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
8219
Michael Wrightd02c5b62014-02-10 15:10:22 -08008220 // press BTN_STYLUS, release BTN_STYLUS
8221 processKey(mapper, BTN_STYLUS, 1);
8222 processSync(mapper);
8223 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8224 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008225 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
8226
8227 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8228 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8229 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008230
8231 processKey(mapper, BTN_STYLUS, 0);
8232 processSync(mapper);
8233 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008234 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008235 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008236
8237 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008238 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008239 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008240
8241 // press BTN_STYLUS2, release BTN_STYLUS2
8242 processKey(mapper, BTN_STYLUS2, 1);
8243 processSync(mapper);
8244 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8245 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008246 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
8247
8248 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8249 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8250 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008251
8252 processKey(mapper, BTN_STYLUS2, 0);
8253 processSync(mapper);
8254 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008255 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008256 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008257
8258 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008259 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008260 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008261
8262 // release touch
8263 processId(mapper, -1);
8264 processSync(mapper);
8265 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8266 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8267 ASSERT_EQ(0, motionArgs.buttonState);
8268}
8269
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008270TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleMappedStylusButtons) {
8271 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008272 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008273 prepareAxes(POSITION | ID | SLOT);
Arpit Singha8c236b2023-04-25 13:56:05 +00008274 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008275
8276 mFakeEventHub->addKey(EVENTHUB_ID, BTN_A, 0, AKEYCODE_STYLUS_BUTTON_PRIMARY, 0);
8277 mFakeEventHub->addKey(EVENTHUB_ID, 0, 0xabcd, AKEYCODE_STYLUS_BUTTON_SECONDARY, 0);
8278
8279 // Touch down.
8280 processId(mapper, 1);
8281 processPosition(mapper, 100, 200);
8282 processSync(mapper);
8283 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8284 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithButtonState(0))));
8285
8286 // Press and release button mapped to the primary stylus button.
8287 processKey(mapper, BTN_A, 1);
8288 processSync(mapper);
8289 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8290 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
8291 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
8292 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8293 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
8294 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
8295
8296 processKey(mapper, BTN_A, 0);
8297 processSync(mapper);
8298 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8299 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithButtonState(0))));
8300 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8301 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
8302
8303 // Press and release the HID usage mapped to the secondary stylus button.
8304 processHidUsage(mapper, 0xabcd, 1);
8305 processSync(mapper);
8306 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8307 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
8308 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY))));
8309 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8310 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
8311 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY))));
8312
8313 processHidUsage(mapper, 0xabcd, 0);
8314 processSync(mapper);
8315 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8316 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithButtonState(0))));
8317 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8318 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
8319
8320 // Release touch.
8321 processId(mapper, -1);
8322 processSync(mapper);
8323 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8324 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
8325}
8326
Michael Wrightd02c5b62014-02-10 15:10:22 -08008327TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008328 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008329 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008330 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00008331 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008332
8333 NotifyMotionArgs motionArgs;
8334
8335 // default tool type is finger
8336 processId(mapper, 1);
8337 processPosition(mapper, 100, 200);
8338 processSync(mapper);
8339 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8340 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008341 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008342
8343 // eraser
8344 processKey(mapper, BTN_TOOL_RUBBER, 1);
8345 processSync(mapper);
8346 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8347 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008348 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008349
8350 // stylus
8351 processKey(mapper, BTN_TOOL_RUBBER, 0);
8352 processKey(mapper, BTN_TOOL_PEN, 1);
8353 processSync(mapper);
8354 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8355 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008356 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008357
8358 // brush
8359 processKey(mapper, BTN_TOOL_PEN, 0);
8360 processKey(mapper, BTN_TOOL_BRUSH, 1);
8361 processSync(mapper);
8362 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8363 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008364 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008365
8366 // pencil
8367 processKey(mapper, BTN_TOOL_BRUSH, 0);
8368 processKey(mapper, BTN_TOOL_PENCIL, 1);
8369 processSync(mapper);
8370 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8371 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008372 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008373
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08008374 // air-brush
Michael Wrightd02c5b62014-02-10 15:10:22 -08008375 processKey(mapper, BTN_TOOL_PENCIL, 0);
8376 processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
8377 processSync(mapper);
8378 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8379 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008380 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008381
8382 // mouse
8383 processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
8384 processKey(mapper, BTN_TOOL_MOUSE, 1);
8385 processSync(mapper);
8386 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8387 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008388 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008389
8390 // lens
8391 processKey(mapper, BTN_TOOL_MOUSE, 0);
8392 processKey(mapper, BTN_TOOL_LENS, 1);
8393 processSync(mapper);
8394 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8395 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008396 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008397
8398 // double-tap
8399 processKey(mapper, BTN_TOOL_LENS, 0);
8400 processKey(mapper, BTN_TOOL_DOUBLETAP, 1);
8401 processSync(mapper);
8402 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8403 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008404 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008405
8406 // triple-tap
8407 processKey(mapper, BTN_TOOL_DOUBLETAP, 0);
8408 processKey(mapper, BTN_TOOL_TRIPLETAP, 1);
8409 processSync(mapper);
8410 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8411 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008412 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008413
8414 // quad-tap
8415 processKey(mapper, BTN_TOOL_TRIPLETAP, 0);
8416 processKey(mapper, BTN_TOOL_QUADTAP, 1);
8417 processSync(mapper);
8418 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8419 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008420 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008421
8422 // finger
8423 processKey(mapper, BTN_TOOL_QUADTAP, 0);
8424 processKey(mapper, BTN_TOOL_FINGER, 1);
8425 processSync(mapper);
8426 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8427 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008428 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008429
8430 // stylus trumps finger
8431 processKey(mapper, BTN_TOOL_PEN, 1);
8432 processSync(mapper);
8433 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8434 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008435 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008436
8437 // eraser trumps stylus
8438 processKey(mapper, BTN_TOOL_RUBBER, 1);
8439 processSync(mapper);
8440 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8441 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008442 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008443
8444 // mouse trumps eraser
8445 processKey(mapper, BTN_TOOL_MOUSE, 1);
8446 processSync(mapper);
8447 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8448 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008449 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008450
8451 // MT tool type trumps BTN tool types: MT_TOOL_FINGER
8452 processToolType(mapper, MT_TOOL_FINGER); // this is the first time we send MT_TOOL_TYPE
8453 processSync(mapper);
8454 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8455 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008456 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008457
8458 // MT tool type trumps BTN tool types: MT_TOOL_PEN
8459 processToolType(mapper, MT_TOOL_PEN);
8460 processSync(mapper);
8461 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8462 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008463 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008464
8465 // back to default tool type
8466 processToolType(mapper, -1); // use a deliberately undefined tool type, for testing
8467 processKey(mapper, BTN_TOOL_MOUSE, 0);
8468 processKey(mapper, BTN_TOOL_RUBBER, 0);
8469 processKey(mapper, BTN_TOOL_PEN, 0);
8470 processKey(mapper, BTN_TOOL_FINGER, 0);
8471 processSync(mapper);
8472 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8473 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008474 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008475}
8476
8477TEST_F(MultiTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008478 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008479 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008480 prepareAxes(POSITION | ID | SLOT);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008481 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00008482 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008483
8484 NotifyMotionArgs motionArgs;
8485
8486 // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0
8487 processId(mapper, 1);
8488 processPosition(mapper, 100, 200);
8489 processSync(mapper);
8490 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8491 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8492 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8493 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8494
8495 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8496 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8497 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8498 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8499
8500 // move a little
8501 processPosition(mapper, 150, 250);
8502 processSync(mapper);
8503 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8504 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8505 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8506 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8507
8508 // down when BTN_TOUCH is pressed, pressure defaults to 1
8509 processKey(mapper, BTN_TOUCH, 1);
8510 processSync(mapper);
8511 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8512 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8513 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8514 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8515
8516 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8517 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8518 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8519 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8520
8521 // up when BTN_TOUCH is released, hover restored
8522 processKey(mapper, BTN_TOUCH, 0);
8523 processSync(mapper);
8524 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8525 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8526 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8527 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8528
8529 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8530 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8531 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8532 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8533
8534 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8535 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8536 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8537 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8538
8539 // exit hover when pointer goes away
8540 processId(mapper, -1);
8541 processSync(mapper);
8542 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8543 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8544 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8545 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8546}
8547
8548TEST_F(MultiTouchInputMapperTest, Process_WhenAbsMTPressureIsPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008549 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008550 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008551 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00008552 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008553
8554 NotifyMotionArgs motionArgs;
8555
8556 // initially hovering because pressure is 0
8557 processId(mapper, 1);
8558 processPosition(mapper, 100, 200);
8559 processPressure(mapper, 0);
8560 processSync(mapper);
8561 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8562 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8563 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8564 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8565
8566 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8567 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8568 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8569 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8570
8571 // move a little
8572 processPosition(mapper, 150, 250);
8573 processSync(mapper);
8574 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8575 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8576 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8577 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8578
8579 // down when pressure becomes non-zero
8580 processPressure(mapper, RAW_PRESSURE_MAX);
8581 processSync(mapper);
8582 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8583 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8584 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8585 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8586
8587 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8588 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8589 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8590 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8591
8592 // up when pressure becomes 0, hover restored
8593 processPressure(mapper, 0);
8594 processSync(mapper);
8595 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8596 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8597 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8598 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8599
8600 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8601 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8602 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8603 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8604
8605 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8606 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8607 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8608 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8609
8610 // exit hover when pointer goes away
8611 processId(mapper, -1);
8612 processSync(mapper);
8613 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8614 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8615 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8616 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8617}
8618
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008619/**
8620 * Set the input device port <--> display port associations, and check that the
8621 * events are routed to the display that matches the display port.
8622 * This can be checked by looking at the displayId of the resulting NotifyMotionArgs.
8623 */
8624TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayPort) {
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008625 const std::string usb2 = "USB2";
8626 const uint8_t hdmi1 = 0;
8627 const uint8_t hdmi2 = 1;
8628 const std::string secondaryUniqueId = "uniqueId2";
Michael Wrightfe3de7d2020-07-02 19:05:30 +01008629 constexpr ViewportType type = ViewportType::EXTERNAL;
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008630
8631 addConfigurationProperty("touch.deviceType", "touchScreen");
8632 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008633 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008634
8635 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
8636 mFakePolicy->addInputPortAssociation(usb2, hdmi2);
8637
8638 // We are intentionally not adding the viewport for display 1 yet. Since the port association
8639 // for this input device is specified, and the matching viewport is not present,
8640 // the input device should be disabled (at the mapper level).
8641
8642 // Add viewport for display 2 on hdmi2
8643 prepareSecondaryDisplay(type, hdmi2);
8644 // Send a touch event
8645 processPosition(mapper, 100, 100);
8646 processSync(mapper);
8647 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
8648
8649 // Add viewport for display 1 on hdmi1
Michael Wrighta9cf4192022-12-01 23:46:39 +00008650 prepareDisplay(ui::ROTATION_0, hdmi1);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008651 // Send a touch event again
8652 processPosition(mapper, 100, 100);
8653 processSync(mapper);
8654
8655 NotifyMotionArgs args;
8656 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8657 ASSERT_EQ(DISPLAY_ID, args.displayId);
8658}
Michael Wrightd02c5b62014-02-10 15:10:22 -08008659
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008660TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayUniqueId) {
8661 addConfigurationProperty("touch.deviceType", "touchScreen");
8662 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008663 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008664
8665 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID);
8666
Michael Wrighta9cf4192022-12-01 23:46:39 +00008667 prepareDisplay(ui::ROTATION_0);
8668 prepareVirtualDisplay(ui::ROTATION_0);
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008669
8670 // Send a touch event
8671 processPosition(mapper, 100, 100);
8672 processSync(mapper);
8673
8674 NotifyMotionArgs args;
8675 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8676 ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId);
8677}
8678
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008679TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01008680 prepareSecondaryDisplay(ViewportType::EXTERNAL);
Garfield Tan888a6a42020-01-09 11:39:16 -08008681
Michael Wrighta9cf4192022-12-01 23:46:39 +00008682 prepareDisplay(ui::ROTATION_0);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008683 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008684 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008685
Josep del Río2d8c79a2023-01-23 19:33:50 +00008686 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008687
8688 NotifyMotionArgs motionArgs;
8689 processPosition(mapper, 100, 100);
8690 processSync(mapper);
8691
8692 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8693 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008694 ASSERT_EQ(ui::LogicalDisplayId::INVALID, motionArgs.displayId);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008695}
8696
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008697/**
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008698 * Ensure that the readTime is set to the SYN_REPORT value when processing touch events.
8699 */
8700TEST_F(MultiTouchInputMapperTest, Process_SendsReadTime) {
8701 addConfigurationProperty("touch.deviceType", "touchScreen");
8702 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008703 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008704
Michael Wrighta9cf4192022-12-01 23:46:39 +00008705 prepareDisplay(ui::ROTATION_0);
Harry Cutts33476232023-01-30 19:57:29 +00008706 process(mapper, 10, /*readTime=*/11, EV_ABS, ABS_MT_TRACKING_ID, 1);
8707 process(mapper, 15, /*readTime=*/16, EV_ABS, ABS_MT_POSITION_X, 100);
8708 process(mapper, 20, /*readTime=*/21, EV_ABS, ABS_MT_POSITION_Y, 100);
8709 process(mapper, 25, /*readTime=*/26, EV_SYN, SYN_REPORT, 0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008710
8711 NotifyMotionArgs args;
8712 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8713 ASSERT_EQ(26, args.readTime);
8714
Harry Cutts33476232023-01-30 19:57:29 +00008715 process(mapper, 30, /*readTime=*/31, EV_ABS, ABS_MT_POSITION_X, 110);
8716 process(mapper, 30, /*readTime=*/32, EV_ABS, ABS_MT_POSITION_Y, 220);
8717 process(mapper, 30, /*readTime=*/33, EV_SYN, SYN_REPORT, 0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008718
8719 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8720 ASSERT_EQ(33, args.readTime);
8721}
8722
8723/**
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008724 * When the viewport is not active (isActive=false), the touch mapper should be disabled and the
8725 * events should not be delivered to the listener.
8726 */
8727TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreDropped) {
8728 addConfigurationProperty("touch.deviceType", "touchScreen");
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008729 // Don't set touch.enableForInactiveViewport to verify the default behavior.
Michael Wrighta9cf4192022-12-01 23:46:39 +00008730 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008731 /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008732 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008733 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008734 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008735
8736 NotifyMotionArgs motionArgs;
8737 processPosition(mapper, 100, 100);
8738 processSync(mapper);
8739
8740 mFakeListener->assertNotifyMotionWasNotCalled();
8741}
8742
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008743/**
8744 * When the viewport is not active (isActive=false) and touch.enableForInactiveViewport is true,
8745 * the touch mapper can process the events and the events can be delivered to the listener.
8746 */
8747TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreProcessed) {
8748 addConfigurationProperty("touch.deviceType", "touchScreen");
8749 addConfigurationProperty("touch.enableForInactiveViewport", "1");
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);
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008753 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008754 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008755
8756 NotifyMotionArgs motionArgs;
8757 processPosition(mapper, 100, 100);
8758 processSync(mapper);
8759
8760 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8761 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8762}
8763
Josh Thielene986aed2023-06-01 14:17:30 +00008764/**
8765 * When the viewport is deactivated (isActive transitions from true to false),
8766 * and touch.enableForInactiveViewport is false, touches prior to the transition
8767 * should be cancelled.
8768 */
Garfield Tanc734e4f2021-01-15 20:01:39 -08008769TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_AbortTouches) {
8770 addConfigurationProperty("touch.deviceType", "touchScreen");
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008771 addConfigurationProperty("touch.enableForInactiveViewport", "0");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008772 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008773 /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008774 std::optional<DisplayViewport> optionalDisplayViewport =
8775 mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
8776 ASSERT_TRUE(optionalDisplayViewport.has_value());
8777 DisplayViewport displayViewport = *optionalDisplayViewport;
8778
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008779 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008780 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008781 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Garfield Tanc734e4f2021-01-15 20:01:39 -08008782
8783 // Finger down
8784 int32_t x = 100, y = 100;
8785 processPosition(mapper, x, y);
8786 processSync(mapper);
8787
8788 NotifyMotionArgs motionArgs;
8789 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8790 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8791
8792 // Deactivate display viewport
8793 displayViewport.isActive = false;
8794 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008795 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008796
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008797 // The ongoing touch should be canceled immediately
8798 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8799 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
8800
8801 // Finger move is ignored
Garfield Tanc734e4f2021-01-15 20:01:39 -08008802 x += 10, y += 10;
8803 processPosition(mapper, x, y);
8804 processSync(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008805 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
Garfield Tanc734e4f2021-01-15 20:01:39 -08008806
8807 // Reactivate display viewport
8808 displayViewport.isActive = true;
8809 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008810 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008811
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008812 // Finger move again starts new gesture
Garfield Tanc734e4f2021-01-15 20:01:39 -08008813 x += 10, y += 10;
8814 processPosition(mapper, x, y);
8815 processSync(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008816 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8817 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008818}
8819
Josh Thielene986aed2023-06-01 14:17:30 +00008820/**
8821 * When the viewport is deactivated (isActive transitions from true to false),
8822 * and touch.enableForInactiveViewport is true, touches prior to the transition
8823 * should not be cancelled.
8824 */
8825TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_TouchesNotAborted) {
8826 addConfigurationProperty("touch.deviceType", "touchScreen");
8827 addConfigurationProperty("touch.enableForInactiveViewport", "1");
8828 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
8829 /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
8830 std::optional<DisplayViewport> optionalDisplayViewport =
8831 mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
8832 ASSERT_TRUE(optionalDisplayViewport.has_value());
8833 DisplayViewport displayViewport = *optionalDisplayViewport;
8834
8835 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8836 prepareAxes(POSITION);
8837 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
8838
8839 // Finger down
8840 int32_t x = 100, y = 100;
8841 processPosition(mapper, x, y);
8842 processSync(mapper);
8843 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8844 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
8845
8846 // Deactivate display viewport
8847 displayViewport.isActive = false;
8848 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
8849 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8850
8851 // The ongoing touch should not be canceled
8852 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
8853
8854 // Finger move is not ignored
8855 x += 10, y += 10;
8856 processPosition(mapper, x, y);
8857 processSync(mapper);
8858 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8859 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
8860
8861 // Reactivate display viewport
8862 displayViewport.isActive = true;
8863 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
8864 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8865
8866 // Finger move continues and does not start new gesture
8867 x += 10, y += 10;
8868 processPosition(mapper, x, y);
8869 processSync(mapper);
8870 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8871 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
8872}
8873
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008874TEST_F(MultiTouchInputMapperTest, VideoFrames_ReceivedByListener) {
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008875 prepareAxes(POSITION);
8876 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008877 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00008878 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008879
8880 NotifyMotionArgs motionArgs;
8881 // Unrotated video frame
8882 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8883 std::vector<TouchVideoFrame> frames{frame};
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008884 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008885 processPosition(mapper, 100, 200);
8886 processSync(mapper);
8887 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8888 ASSERT_EQ(frames, motionArgs.videoFrames);
8889
8890 // Subsequent touch events should not have any videoframes
8891 // This is implemented separately in FakeEventHub,
8892 // but that should match the behaviour of TouchVideoDevice.
8893 processPosition(mapper, 200, 200);
8894 processSync(mapper);
8895 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8896 ASSERT_EQ(std::vector<TouchVideoFrame>(), motionArgs.videoFrames);
8897}
8898
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008899TEST_F(MultiTouchInputMapperTest, VideoFrames_AreNotRotated) {
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008900 prepareAxes(POSITION);
8901 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00008902 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008903 // Unrotated video frame
8904 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8905 NotifyMotionArgs motionArgs;
8906
8907 // Test all 4 orientations
Michael Wrighta9cf4192022-12-01 23:46:39 +00008908 for (ui::Rotation orientation : ftl::enum_range<ui::Rotation>()) {
Harry Cuttsc57cd3c2024-04-24 13:52:55 +00008909 SCOPED_TRACE(StringPrintf("Orientation %s", ftl::enum_string(orientation).c_str()));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008910 clearViewports();
8911 prepareDisplay(orientation);
8912 std::vector<TouchVideoFrame> frames{frame};
8913 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
8914 processPosition(mapper, 100, 200);
8915 processSync(mapper);
8916 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8917 ASSERT_EQ(frames, motionArgs.videoFrames);
8918 }
8919}
8920
8921TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_AreRotated) {
8922 prepareAxes(POSITION);
8923 addConfigurationProperty("touch.deviceType", "touchScreen");
8924 // Since InputReader works in the un-rotated coordinate space, only devices that are not
8925 // orientation-aware are affected by display rotation.
8926 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00008927 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008928 // Unrotated video frame
8929 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8930 NotifyMotionArgs motionArgs;
8931
8932 // Test all 4 orientations
Michael Wrighta9cf4192022-12-01 23:46:39 +00008933 for (ui::Rotation orientation : ftl::enum_range<ui::Rotation>()) {
Harry Cuttsc57cd3c2024-04-24 13:52:55 +00008934 SCOPED_TRACE(StringPrintf("Orientation %s", ftl::enum_string(orientation).c_str()));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008935 clearViewports();
8936 prepareDisplay(orientation);
8937 std::vector<TouchVideoFrame> frames{frame};
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008938 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008939 processPosition(mapper, 100, 200);
8940 processSync(mapper);
8941 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008942 // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction
8943 // compared to the display. This is so that when the window transform (which contains the
8944 // display rotation) is applied later by InputDispatcher, the coordinates end up in the
8945 // window's coordinate space.
8946 frames[0].rotate(getInverseRotation(orientation));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008947 ASSERT_EQ(frames, motionArgs.videoFrames);
lilinnan687e58f2022-07-19 16:00:50 +08008948
8949 // Release finger.
8950 processSync(mapper);
8951 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008952 }
8953}
8954
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008955TEST_F(MultiTouchInputMapperTest, VideoFrames_MultipleFramesAreNotRotated) {
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008956 prepareAxes(POSITION);
8957 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00008958 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008959 // Unrotated video frames. There's no rule that they must all have the same dimensions,
8960 // so mix these.
8961 TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8962 TouchVideoFrame frame2(3, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {1, 3});
8963 TouchVideoFrame frame3(2, 2, {10, 20, 10, 0}, {1, 4});
8964 std::vector<TouchVideoFrame> frames{frame1, frame2, frame3};
8965 NotifyMotionArgs motionArgs;
8966
Michael Wrighta9cf4192022-12-01 23:46:39 +00008967 prepareDisplay(ui::ROTATION_90);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008968 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008969 processPosition(mapper, 100, 200);
8970 processSync(mapper);
8971 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008972 ASSERT_EQ(frames, motionArgs.videoFrames);
8973}
8974
8975TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_MultipleFramesAreRotated) {
8976 prepareAxes(POSITION);
8977 addConfigurationProperty("touch.deviceType", "touchScreen");
8978 // Since InputReader works in the un-rotated coordinate space, only devices that are not
8979 // orientation-aware are affected by display rotation.
8980 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00008981 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008982 // Unrotated video frames. There's no rule that they must all have the same dimensions,
8983 // so mix these.
8984 TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8985 TouchVideoFrame frame2(3, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {1, 3});
8986 TouchVideoFrame frame3(2, 2, {10, 20, 10, 0}, {1, 4});
8987 std::vector<TouchVideoFrame> frames{frame1, frame2, frame3};
8988 NotifyMotionArgs motionArgs;
8989
Michael Wrighta9cf4192022-12-01 23:46:39 +00008990 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008991 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
8992 processPosition(mapper, 100, 200);
8993 processSync(mapper);
8994 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8995 std::for_each(frames.begin(), frames.end(), [](TouchVideoFrame& frame) {
8996 // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction
8997 // compared to the display. This is so that when the window transform (which contains the
8998 // display rotation) is applied later by InputDispatcher, the coordinates end up in the
8999 // window's coordinate space.
Michael Wrighta9cf4192022-12-01 23:46:39 +00009000 frame.rotate(getInverseRotation(ui::ROTATION_90));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009001 });
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009002 ASSERT_EQ(frames, motionArgs.videoFrames);
9003}
9004
Arthur Hung9da14732019-09-02 16:16:58 +08009005/**
9006 * If we had defined port associations, but the viewport is not ready, the touch device would be
9007 * expected to be disabled, and it should be enabled after the viewport has found.
9008 */
9009TEST_F(MultiTouchInputMapperTest, Configure_EnabledForAssociatedDisplay) {
Arthur Hung9da14732019-09-02 16:16:58 +08009010 constexpr uint8_t hdmi2 = 1;
9011 const std::string secondaryUniqueId = "uniqueId2";
Michael Wrightfe3de7d2020-07-02 19:05:30 +01009012 constexpr ViewportType type = ViewportType::EXTERNAL;
Arthur Hung9da14732019-09-02 16:16:58 +08009013
9014 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi2);
9015
9016 addConfigurationProperty("touch.deviceType", "touchScreen");
9017 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00009018 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung9da14732019-09-02 16:16:58 +08009019
9020 ASSERT_EQ(mDevice->isEnabled(), false);
9021
9022 // Add display on hdmi2, the device should be enabled and can receive touch event.
9023 prepareSecondaryDisplay(type, hdmi2);
9024 ASSERT_EQ(mDevice->isEnabled(), true);
9025
9026 // Send a touch event.
9027 processPosition(mapper, 100, 100);
9028 processSync(mapper);
9029
9030 NotifyMotionArgs args;
9031 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9032 ASSERT_EQ(SECONDARY_DISPLAY_ID, args.displayId);
9033}
9034
Arthur Hung421eb1c2020-01-16 00:09:42 +08009035TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleSingleTouch) {
Arthur Hung421eb1c2020-01-16 00:09:42 +08009036 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009037 prepareDisplay(ui::ROTATION_0);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009038 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009039 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung421eb1c2020-01-16 00:09:42 +08009040
9041 NotifyMotionArgs motionArgs;
9042
9043 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
9044 // finger down
9045 processId(mapper, 1);
9046 processPosition(mapper, x1, y1);
9047 processSync(mapper);
9048 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9049 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009050 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009051
9052 // finger move
9053 processId(mapper, 1);
9054 processPosition(mapper, x2, y2);
9055 processSync(mapper);
9056 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9057 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009058 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009059
9060 // finger up.
9061 processId(mapper, -1);
9062 processSync(mapper);
9063 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9064 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009065 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009066
9067 // new finger down
9068 processId(mapper, 1);
9069 processPosition(mapper, x3, y3);
9070 processSync(mapper);
9071 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9072 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009073 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009074}
9075
9076/**
arthurhungcc7f9802020-04-30 17:55:40 +08009077 * Test single touch should be canceled when received the MT_TOOL_PALM event, and the following
9078 * MOVE and UP events should be ignored.
Arthur Hung421eb1c2020-01-16 00:09:42 +08009079 */
arthurhungcc7f9802020-04-30 17:55:40 +08009080TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_SinglePointer) {
Arthur Hung421eb1c2020-01-16 00:09:42 +08009081 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009082 prepareDisplay(ui::ROTATION_0);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009083 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009084 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung421eb1c2020-01-16 00:09:42 +08009085
9086 NotifyMotionArgs motionArgs;
9087
9088 // default tool type is finger
9089 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
arthurhungcc7f9802020-04-30 17:55:40 +08009090 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009091 processPosition(mapper, x1, y1);
9092 processSync(mapper);
9093 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9094 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009095 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009096
9097 // Tool changed to MT_TOOL_PALM expect sending the cancel event.
9098 processToolType(mapper, MT_TOOL_PALM);
9099 processSync(mapper);
9100 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9101 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9102
9103 // Ignore the following MOVE and UP events if had detect a palm event.
arthurhungcc7f9802020-04-30 17:55:40 +08009104 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009105 processPosition(mapper, x2, y2);
9106 processSync(mapper);
9107 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9108
9109 // finger up.
arthurhungcc7f9802020-04-30 17:55:40 +08009110 processId(mapper, INVALID_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009111 processSync(mapper);
9112 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9113
9114 // new finger down
arthurhungcc7f9802020-04-30 17:55:40 +08009115 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009116 processToolType(mapper, MT_TOOL_FINGER);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009117 processPosition(mapper, x3, y3);
9118 processSync(mapper);
9119 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9120 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009121 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009122}
9123
arthurhungbf89a482020-04-17 17:37:55 +08009124/**
arthurhungcc7f9802020-04-30 17:55:40 +08009125 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event from some finger,
9126 * and the rest active fingers could still be allowed to receive the events
arthurhungbf89a482020-04-17 17:37:55 +08009127 */
arthurhungcc7f9802020-04-30 17:55:40 +08009128TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_TwoPointers) {
arthurhungbf89a482020-04-17 17:37:55 +08009129 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009130 prepareDisplay(ui::ROTATION_0);
arthurhungbf89a482020-04-17 17:37:55 +08009131 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009132 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungbf89a482020-04-17 17:37:55 +08009133
9134 NotifyMotionArgs motionArgs;
9135
9136 // default tool type is finger
arthurhungcc7f9802020-04-30 17:55:40 +08009137 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220;
9138 processId(mapper, FIRST_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009139 processPosition(mapper, x1, y1);
9140 processSync(mapper);
9141 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9142 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009143 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungbf89a482020-04-17 17:37:55 +08009144
9145 // Second finger down.
arthurhungcc7f9802020-04-30 17:55:40 +08009146 processSlot(mapper, SECOND_SLOT);
9147 processId(mapper, SECOND_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009148 processPosition(mapper, x2, y2);
arthurhungcc7f9802020-04-30 17:55:40 +08009149 processSync(mapper);
9150 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009151 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009152 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009153
9154 // If the tool type of the first finger changes to MT_TOOL_PALM,
9155 // we expect to receive ACTION_POINTER_UP with cancel flag.
9156 processSlot(mapper, FIRST_SLOT);
9157 processId(mapper, FIRST_TRACKING_ID);
9158 processToolType(mapper, MT_TOOL_PALM);
9159 processSync(mapper);
9160 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009161 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009162 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9163
9164 // The following MOVE events of second finger should be processed.
9165 processSlot(mapper, SECOND_SLOT);
9166 processId(mapper, SECOND_TRACKING_ID);
9167 processPosition(mapper, x2 + 1, y2 + 1);
9168 processSync(mapper);
9169 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9170 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009171 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009172
9173 // First finger up. It used to be in palm mode, and we already generated ACTION_POINTER_UP for
9174 // it. Second finger receive move.
9175 processSlot(mapper, FIRST_SLOT);
9176 processId(mapper, INVALID_TRACKING_ID);
9177 processSync(mapper);
9178 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9179 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009180 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009181
9182 // Second finger keeps moving.
9183 processSlot(mapper, SECOND_SLOT);
9184 processId(mapper, SECOND_TRACKING_ID);
9185 processPosition(mapper, x2 + 2, y2 + 2);
9186 processSync(mapper);
9187 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9188 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009189 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009190
9191 // Second finger up.
9192 processId(mapper, INVALID_TRACKING_ID);
9193 processSync(mapper);
9194 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9195 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9196 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9197}
9198
9199/**
9200 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event, if only 1 finger
9201 * is active, it should send CANCEL after receiving the MT_TOOL_PALM event.
9202 */
9203TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_ShouldCancelWhenAllTouchIsPalm) {
9204 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009205 prepareDisplay(ui::ROTATION_0);
arthurhungcc7f9802020-04-30 17:55:40 +08009206 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009207 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungcc7f9802020-04-30 17:55:40 +08009208
9209 NotifyMotionArgs motionArgs;
9210
9211 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
9212 // First finger down.
9213 processId(mapper, FIRST_TRACKING_ID);
9214 processPosition(mapper, x1, y1);
9215 processSync(mapper);
9216 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9217 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009218 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009219
9220 // Second finger down.
9221 processSlot(mapper, SECOND_SLOT);
9222 processId(mapper, SECOND_TRACKING_ID);
9223 processPosition(mapper, x2, y2);
arthurhungbf89a482020-04-17 17:37:55 +08009224 processSync(mapper);
9225 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009226 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009227 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungbf89a482020-04-17 17:37:55 +08009228
arthurhungcc7f9802020-04-30 17:55:40 +08009229 // If the tool type of the first finger changes to MT_TOOL_PALM,
9230 // we expect to receive ACTION_POINTER_UP with cancel flag.
9231 processSlot(mapper, FIRST_SLOT);
9232 processId(mapper, FIRST_TRACKING_ID);
9233 processToolType(mapper, MT_TOOL_PALM);
9234 processSync(mapper);
9235 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009236 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009237 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9238
9239 // Second finger keeps moving.
9240 processSlot(mapper, SECOND_SLOT);
9241 processId(mapper, SECOND_TRACKING_ID);
9242 processPosition(mapper, x2 + 1, y2 + 1);
9243 processSync(mapper);
9244 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9245 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9246
9247 // second finger becomes palm, receive cancel due to only 1 finger is active.
9248 processId(mapper, SECOND_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009249 processToolType(mapper, MT_TOOL_PALM);
9250 processSync(mapper);
9251 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9252 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9253
arthurhungcc7f9802020-04-30 17:55:40 +08009254 // third finger down.
9255 processSlot(mapper, THIRD_SLOT);
9256 processId(mapper, THIRD_TRACKING_ID);
9257 processToolType(mapper, MT_TOOL_FINGER);
arthurhungbf89a482020-04-17 17:37:55 +08009258 processPosition(mapper, x3, y3);
9259 processSync(mapper);
arthurhungbf89a482020-04-17 17:37:55 +08009260 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9261 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009262 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009263 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009264
9265 // third finger move
9266 processId(mapper, THIRD_TRACKING_ID);
9267 processPosition(mapper, x3 + 1, y3 + 1);
9268 processSync(mapper);
9269 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9270 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9271
9272 // first finger up, third finger receive move.
9273 processSlot(mapper, FIRST_SLOT);
9274 processId(mapper, INVALID_TRACKING_ID);
9275 processSync(mapper);
9276 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9277 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009278 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009279
9280 // second finger up, third finger receive move.
9281 processSlot(mapper, SECOND_SLOT);
9282 processId(mapper, INVALID_TRACKING_ID);
9283 processSync(mapper);
9284 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9285 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009286 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009287
9288 // third finger up.
9289 processSlot(mapper, THIRD_SLOT);
9290 processId(mapper, INVALID_TRACKING_ID);
9291 processSync(mapper);
9292 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9293 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9294 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9295}
9296
9297/**
9298 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event from some finger,
9299 * and the active finger could still be allowed to receive the events
9300 */
9301TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_KeepFirstPointer) {
9302 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009303 prepareDisplay(ui::ROTATION_0);
arthurhungcc7f9802020-04-30 17:55:40 +08009304 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009305 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungcc7f9802020-04-30 17:55:40 +08009306
9307 NotifyMotionArgs motionArgs;
9308
9309 // default tool type is finger
9310 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220;
9311 processId(mapper, FIRST_TRACKING_ID);
9312 processPosition(mapper, x1, y1);
9313 processSync(mapper);
9314 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9315 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009316 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009317
9318 // Second finger down.
9319 processSlot(mapper, SECOND_SLOT);
9320 processId(mapper, SECOND_TRACKING_ID);
9321 processPosition(mapper, x2, y2);
9322 processSync(mapper);
9323 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009324 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009325 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009326
9327 // If the tool type of the second finger changes to MT_TOOL_PALM,
9328 // we expect to receive ACTION_POINTER_UP with cancel flag.
9329 processId(mapper, SECOND_TRACKING_ID);
9330 processToolType(mapper, MT_TOOL_PALM);
9331 processSync(mapper);
9332 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009333 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009334 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9335
9336 // The following MOVE event should be processed.
9337 processSlot(mapper, FIRST_SLOT);
9338 processId(mapper, FIRST_TRACKING_ID);
9339 processPosition(mapper, x1 + 1, y1 + 1);
9340 processSync(mapper);
9341 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9342 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009343 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009344
9345 // second finger up.
9346 processSlot(mapper, SECOND_SLOT);
9347 processId(mapper, INVALID_TRACKING_ID);
9348 processSync(mapper);
9349 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9350 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9351
9352 // first finger keep moving
9353 processSlot(mapper, FIRST_SLOT);
9354 processId(mapper, FIRST_TRACKING_ID);
9355 processPosition(mapper, x1 + 2, y1 + 2);
9356 processSync(mapper);
9357 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9358 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9359
9360 // first finger up.
9361 processId(mapper, INVALID_TRACKING_ID);
9362 processSync(mapper);
9363 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9364 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9365 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
arthurhungbf89a482020-04-17 17:37:55 +08009366}
9367
Arthur Hung9ad18942021-06-19 02:04:46 +00009368/**
9369 * Test multi-touch should sent ACTION_POINTER_UP/ACTION_UP when received the INVALID_TRACKING_ID,
9370 * to prevent the driver side may send unexpected data after set tracking id as INVALID_TRACKING_ID
9371 * cause slot be valid again.
9372 */
9373TEST_F(MultiTouchInputMapperTest, Process_MultiTouch_WithInvalidTrackingId) {
9374 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009375 prepareDisplay(ui::ROTATION_0);
Arthur Hung9ad18942021-06-19 02:04:46 +00009376 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009377 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung9ad18942021-06-19 02:04:46 +00009378
9379 NotifyMotionArgs motionArgs;
9380
9381 constexpr int32_t x1 = 100, y1 = 200, x2 = 0, y2 = 0;
9382 // First finger down.
9383 processId(mapper, FIRST_TRACKING_ID);
9384 processPosition(mapper, x1, y1);
9385 processPressure(mapper, RAW_PRESSURE_MAX);
9386 processSync(mapper);
9387 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9388 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009389 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009390
9391 // First finger move.
9392 processId(mapper, FIRST_TRACKING_ID);
9393 processPosition(mapper, x1 + 1, y1 + 1);
9394 processPressure(mapper, RAW_PRESSURE_MAX);
9395 processSync(mapper);
9396 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9397 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009398 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009399
9400 // Second finger down.
9401 processSlot(mapper, SECOND_SLOT);
9402 processId(mapper, SECOND_TRACKING_ID);
9403 processPosition(mapper, x2, y2);
9404 processPressure(mapper, RAW_PRESSURE_MAX);
9405 processSync(mapper);
9406 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009407 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009408 ASSERT_EQ(uint32_t(2), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009409
9410 // second finger up with some unexpected data.
9411 processSlot(mapper, SECOND_SLOT);
9412 processId(mapper, INVALID_TRACKING_ID);
9413 processPosition(mapper, x2, y2);
9414 processSync(mapper);
9415 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009416 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009417 ASSERT_EQ(uint32_t(2), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009418
9419 // first finger up with some unexpected data.
9420 processSlot(mapper, FIRST_SLOT);
9421 processId(mapper, INVALID_TRACKING_ID);
9422 processPosition(mapper, x2, y2);
9423 processPressure(mapper, RAW_PRESSURE_MAX);
9424 processSync(mapper);
9425 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9426 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009427 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009428}
9429
Arpit Singh4b4a4572023-11-24 18:19:56 +00009430TEST_F(MultiTouchInputMapperTest, Reset_RepopulatesMultiTouchState) {
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009431 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009432 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009433 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009434 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009435
9436 // First finger down.
Arpit Singh4b4a4572023-11-24 18:19:56 +00009437 constexpr int32_t x1 = 100, y1 = 200, x2 = 300, y2 = 400;
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009438 processId(mapper, FIRST_TRACKING_ID);
Arpit Singh4b4a4572023-11-24 18:19:56 +00009439 processPosition(mapper, x1, y1);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009440 processPressure(mapper, RAW_PRESSURE_MAX);
9441 processSync(mapper);
9442 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9443 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
9444
9445 // Second finger down.
9446 processSlot(mapper, SECOND_SLOT);
9447 processId(mapper, SECOND_TRACKING_ID);
Arpit Singh4b4a4572023-11-24 18:19:56 +00009448 processPosition(mapper, x2, y2);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009449 processPressure(mapper, RAW_PRESSURE_MAX);
9450 processSync(mapper);
9451 ASSERT_NO_FATAL_FAILURE(
9452 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(ACTION_POINTER_1_DOWN)));
9453
Arpit Singh4b4a4572023-11-24 18:19:56 +00009454 // Set MT Slot state to be repopulated for the required slots
9455 std::vector<int32_t> mtSlotValues(RAW_SLOT_MAX + 1, -1);
9456 mtSlotValues[0] = FIRST_TRACKING_ID;
9457 mtSlotValues[1] = SECOND_TRACKING_ID;
9458 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_TRACKING_ID, mtSlotValues);
9459
9460 mtSlotValues[0] = x1;
9461 mtSlotValues[1] = x2;
9462 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_POSITION_X, mtSlotValues);
9463
9464 mtSlotValues[0] = y1;
9465 mtSlotValues[1] = y2;
9466 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_POSITION_Y, mtSlotValues);
9467
9468 mtSlotValues[0] = RAW_PRESSURE_MAX;
9469 mtSlotValues[1] = RAW_PRESSURE_MAX;
9470 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_PRESSURE, mtSlotValues);
9471
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009472 // Reset the mapper. When the mapper is reset, we expect the current multi-touch state to be
Arpit Singh4b4a4572023-11-24 18:19:56 +00009473 // repopulated. Resetting should cancel the ongoing gesture.
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00009474 resetMapper(mapper, ARBITRARY_TIME);
9475 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9476 WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009477
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009478 // Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
9479 // the existing touch state to generate a down event.
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009480 processPosition(mapper, 301, 302);
9481 processSync(mapper);
9482 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9483 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPressure(1.f))));
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009484 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9485 AllOf(WithMotionAction(ACTION_POINTER_1_DOWN), WithPressure(1.f))));
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009486
9487 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9488}
9489
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009490TEST_F(MultiTouchInputMapperTest, Reset_PreservesLastTouchState_NoPointersDown) {
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009491 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009492 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009493 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009494 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009495
9496 // First finger touches down and releases.
9497 processId(mapper, FIRST_TRACKING_ID);
9498 processPosition(mapper, 100, 200);
9499 processPressure(mapper, RAW_PRESSURE_MAX);
9500 processSync(mapper);
9501 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9502 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
9503 processId(mapper, INVALID_TRACKING_ID);
9504 processSync(mapper);
9505 ASSERT_NO_FATAL_FAILURE(
9506 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
9507
9508 // Reset the mapper. When the mapper is reset, we expect it to restore the latest
9509 // raw state where no pointers are down.
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00009510 resetMapper(mapper, ARBITRARY_TIME);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009511 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9512
9513 // Send an empty sync frame. Since there are no pointers, no events are generated.
9514 processSync(mapper);
9515 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9516}
9517
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009518TEST_F(MultiTouchInputMapperTest, StylusSourceIsAddedDynamicallyFromToolType) {
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009519 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009520 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009521 prepareAxes(POSITION | ID | SLOT | PRESSURE | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009522 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009523 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009524
9525 // Even if the device supports reporting the ABS_MT_TOOL_TYPE axis, which could give it the
9526 // ability to report MT_TOOL_PEN, we do not report the device as coming from a stylus source.
9527 // Due to limitations in the evdev protocol, we cannot say for certain that a device is capable
9528 // of reporting stylus events just because it supports ABS_MT_TOOL_TYPE.
9529 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
9530
9531 // However, if the device ever ends up reporting an event with MT_TOOL_PEN, it should be
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009532 // reported with the stylus source.
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009533 processId(mapper, FIRST_TRACKING_ID);
9534 processToolType(mapper, MT_TOOL_PEN);
9535 processPosition(mapper, 100, 200);
9536 processPressure(mapper, RAW_PRESSURE_MAX);
9537 processSync(mapper);
9538 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9539 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
9540 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009541 WithToolType(ToolType::STYLUS))));
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009542
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009543 // Now that we know the device supports styluses, ensure that the device is re-configured with
9544 // the stylus source.
9545 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, mapper.getSources());
9546 {
9547 const auto& devices = mReader->getInputDevices();
9548 auto deviceInfo =
9549 std::find_if(devices.begin(), devices.end(),
9550 [](const InputDeviceInfo& info) { return info.getId() == DEVICE_ID; });
9551 LOG_ALWAYS_FATAL_IF(deviceInfo == devices.end(), "Cannot find InputDevice");
9552 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, deviceInfo->getSources());
9553 }
9554
9555 // Ensure the device was not reset to prevent interruptions of any ongoing gestures.
9556 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
9557
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009558 processId(mapper, INVALID_TRACKING_ID);
9559 processSync(mapper);
9560 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9561 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
9562 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009563 WithToolType(ToolType::STYLUS))));
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009564}
9565
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009566// --- MultiTouchInputMapperTest_ExternalDevice ---
9567
9568class MultiTouchInputMapperTest_ExternalDevice : public MultiTouchInputMapperTest {
9569protected:
Chris Yea52ade12020-08-27 16:49:20 -07009570 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL); }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009571};
9572
9573/**
9574 * Expect fallback to internal viewport if device is external and external viewport is not present.
9575 */
9576TEST_F(MultiTouchInputMapperTest_ExternalDevice, Viewports_Fallback) {
9577 prepareAxes(POSITION);
9578 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009579 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00009580 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009581
9582 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
9583
9584 NotifyMotionArgs motionArgs;
9585
9586 // Expect the event to be sent to the internal viewport,
9587 // because an external viewport is not present.
9588 processPosition(mapper, 100, 100);
9589 processSync(mapper);
9590 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009591 ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, motionArgs.displayId);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009592
9593 // Expect the event to be sent to the external viewport if it is present.
Michael Wrightfe3de7d2020-07-02 19:05:30 +01009594 prepareSecondaryDisplay(ViewportType::EXTERNAL);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009595 processPosition(mapper, 100, 100);
9596 processSync(mapper);
9597 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9598 ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
9599}
Arthur Hung4197f6b2020-03-16 15:39:59 +08009600
Prabir Pradhan3ed7e352024-05-03 23:59:43 +00009601// TODO(b/281840344): Remove the test when the old touchpad stack is removed. It is currently
9602// unclear what the behavior of the touchpad logic in TouchInputMapper should do after the
9603// PointerChoreographer refactor.
9604TEST_F(MultiTouchInputMapperTest, DISABLED_Process_TouchpadPointer) {
Harry Cutts8722be92024-04-05 14:46:05 +00009605 // prepare device
Michael Wrighta9cf4192022-12-01 23:46:39 +00009606 prepareDisplay(ui::ROTATION_0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009607 prepareAxes(POSITION | ID | SLOT);
9608 mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
9609 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00009610 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009611 // run uncaptured pointer tests - pushes out generic events
9612 // FINGER 0 DOWN
9613 processId(mapper, 3);
9614 processPosition(mapper, 100, 100);
9615 processKey(mapper, BTN_TOUCH, 1);
9616 processSync(mapper);
9617
9618 // start at (100,100), cursor should be at (0,0) * scale
9619 NotifyMotionArgs args;
9620 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9621 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
9622 ASSERT_NO_FATAL_FAILURE(
9623 assertPointerCoords(args.pointerCoords[0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
9624
9625 // FINGER 0 MOVE
9626 processPosition(mapper, 200, 200);
9627 processSync(mapper);
9628
9629 // compute scaling to help with touch position checking
9630 float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
9631 float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
9632 float scale =
9633 mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
9634
9635 // translate from (100,100) -> (200,200), cursor should have changed to (100,100) * scale)
9636 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9637 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
9638 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], 100 * scale, 100 * scale, 0,
9639 0, 0, 0, 0, 0, 0, 0));
LiZhihong758eb562022-11-03 15:28:29 +08009640
9641 // BUTTON DOWN
9642 processKey(mapper, BTN_LEFT, 1);
9643 processSync(mapper);
9644
9645 // touchinputmapper design sends a move before button press
9646 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9647 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
9648 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9649 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, args.action);
9650
9651 // BUTTON UP
9652 processKey(mapper, BTN_LEFT, 0);
9653 processSync(mapper);
9654
9655 // touchinputmapper design sends a move after button release
9656 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9657 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, args.action);
9658 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9659 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009660}
9661
Harry Cutts8722be92024-04-05 14:46:05 +00009662TEST_F(MultiTouchInputMapperTest, Touchpad_GetSources) {
Michael Wrighta9cf4192022-12-01 23:46:39 +00009663 prepareDisplay(ui::ROTATION_0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009664 prepareAxes(POSITION | ID | SLOT);
9665 mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
Hiroki Sato25040232024-02-22 17:21:22 +09009666 mFakePolicy->setPointerCapture(/*window=*/nullptr);
Arpit Singha8c236b2023-04-25 13:56:05 +00009667 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009668
Josep del Río2d8c79a2023-01-23 19:33:50 +00009669 // uncaptured touchpad should be a pointer device
9670 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009671}
9672
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009673// --- BluetoothMultiTouchInputMapperTest ---
9674
9675class BluetoothMultiTouchInputMapperTest : public MultiTouchInputMapperTest {
9676protected:
9677 void SetUp() override {
9678 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL, BUS_BLUETOOTH);
9679 }
9680};
9681
9682TEST_F(BluetoothMultiTouchInputMapperTest, TimestampSmoothening) {
9683 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009684 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009685 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009686 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009687
9688 nsecs_t kernelEventTime = ARBITRARY_TIME;
9689 nsecs_t expectedEventTime = ARBITRARY_TIME;
9690 // Touch down.
9691 processId(mapper, FIRST_TRACKING_ID);
9692 processPosition(mapper, 100, 200);
9693 processPressure(mapper, RAW_PRESSURE_MAX);
9694 processSync(mapper, ARBITRARY_TIME);
9695 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9696 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithEventTime(ARBITRARY_TIME))));
9697
9698 // Process several events that come in quick succession, according to their timestamps.
9699 for (int i = 0; i < 3; i++) {
9700 constexpr static nsecs_t delta = ms2ns(1);
9701 static_assert(delta < MIN_BLUETOOTH_TIMESTAMP_DELTA);
9702 kernelEventTime += delta;
9703 expectedEventTime += MIN_BLUETOOTH_TIMESTAMP_DELTA;
9704
9705 processPosition(mapper, 101 + i, 201 + i);
9706 processSync(mapper, kernelEventTime);
9707 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9708 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
9709 WithEventTime(expectedEventTime))));
9710 }
9711
9712 // Release the touch.
9713 processId(mapper, INVALID_TRACKING_ID);
9714 processPressure(mapper, RAW_PRESSURE_MIN);
9715 processSync(mapper, ARBITRARY_TIME + ms2ns(50));
9716 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9717 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
9718 WithEventTime(ARBITRARY_TIME + ms2ns(50)))));
9719}
9720
9721// --- MultiTouchPointerModeTest ---
9722
HQ Liue6983c72022-04-19 22:14:56 +00009723class MultiTouchPointerModeTest : public MultiTouchInputMapperTest {
9724protected:
9725 float mPointerMovementScale;
9726 float mPointerXZoomScale;
9727 void preparePointerMode(int xAxisResolution, int yAxisResolution) {
9728 addConfigurationProperty("touch.deviceType", "pointer");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009729 prepareDisplay(ui::ROTATION_0);
HQ Liue6983c72022-04-19 22:14:56 +00009730
9731 prepareAxes(POSITION);
9732 prepareAbsoluteAxisResolution(xAxisResolution, yAxisResolution);
9733 // In order to enable swipe and freeform gesture in pointer mode, pointer capture
9734 // needs to be disabled, and the pointer gesture needs to be enabled.
Hiroki Sato25040232024-02-22 17:21:22 +09009735 mFakePolicy->setPointerCapture(/*window=*/nullptr);
HQ Liue6983c72022-04-19 22:14:56 +00009736 mFakePolicy->setPointerGestureEnabled(true);
HQ Liue6983c72022-04-19 22:14:56 +00009737
9738 float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
9739 float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
9740 mPointerMovementScale =
9741 mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
9742 mPointerXZoomScale =
9743 mFakePolicy->getPointerGestureZoomSpeedRatio() * displayDiagonal / rawDiagonal;
9744 }
9745
9746 void prepareAbsoluteAxisResolution(int xAxisResolution, int yAxisResolution) {
9747 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX,
9748 /*flat*/ 0,
9749 /*fuzz*/ 0, /*resolution*/ xAxisResolution);
9750 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX,
9751 /*flat*/ 0,
9752 /*fuzz*/ 0, /*resolution*/ yAxisResolution);
9753 }
9754};
9755
9756/**
9757 * Two fingers down on a pointer mode touch pad. The width
9758 * of the two finger is larger than 1/4 of the touch pack diagnal length. However, it
9759 * is smaller than the fixed min physical length 30mm. Two fingers' distance must
9760 * be greater than the both value to be freeform gesture, so that after two
9761 * fingers start to move downwards, the gesture should be swipe.
9762 */
9763TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthSwipe) {
9764 // The min freeform gesture width is 25units/mm x 30mm = 750
9765 // which is greater than fraction of the diagnal length of the touchpad (349).
9766 // Thus, MaxSwipWidth is 750.
Harry Cutts33476232023-01-30 19:57:29 +00009767 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +00009768 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009769 NotifyMotionArgs motionArgs;
9770
9771 // Two fingers down at once.
9772 // The two fingers are 450 units apart, expects the current gesture to be PRESS
9773 // Pointer's initial position is used the [0,0] coordinate.
9774 int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125;
9775
9776 processId(mapper, FIRST_TRACKING_ID);
9777 processPosition(mapper, x1, y1);
9778 processMTSync(mapper);
9779 processId(mapper, SECOND_TRACKING_ID);
9780 processPosition(mapper, x2, y2);
9781 processMTSync(mapper);
9782 processSync(mapper);
9783
9784 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009785 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009786 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009787 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009788 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009789 ASSERT_NO_FATAL_FAILURE(
9790 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9791
9792 // It should be recognized as a SWIPE gesture when two fingers start to move down,
9793 // that there should be 1 pointer.
9794 int32_t movingDistance = 200;
9795 y1 += movingDistance;
9796 y2 += movingDistance;
9797
9798 processId(mapper, FIRST_TRACKING_ID);
9799 processPosition(mapper, x1, y1);
9800 processMTSync(mapper);
9801 processId(mapper, SECOND_TRACKING_ID);
9802 processPosition(mapper, x2, y2);
9803 processMTSync(mapper);
9804 processSync(mapper);
9805
9806 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009807 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009808 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009809 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009810 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009811 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
9812 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9813 0, 0, 0, 0));
9814}
9815
9816/**
9817 * Two fingers down on a pointer mode touch pad. The width of the two finger is larger
9818 * than the minimum freeform gesture width, 30mm. However, it is smaller than 1/4 of
9819 * the touch pack diagnal length. Two fingers' distance must be greater than the both
9820 * value to be freeform gesture, so that after two fingers start to move downwards,
9821 * the gesture should be swipe.
9822 */
9823TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthLowResolutionSwipe) {
9824 // The min freeform gesture width is 5units/mm x 30mm = 150
9825 // which is greater than fraction of the diagnal length of the touchpad (349).
9826 // Thus, MaxSwipWidth is the fraction of the diagnal length, 349.
Harry Cutts33476232023-01-30 19:57:29 +00009827 preparePointerMode(/*xResolution=*/5, /*yResolution=*/5);
Arpit Singha8c236b2023-04-25 13:56:05 +00009828 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009829 NotifyMotionArgs motionArgs;
9830
9831 // Two fingers down at once.
9832 // The two fingers are 250 units apart, expects the current gesture to be PRESS
9833 // Pointer's initial position is used the [0,0] coordinate.
9834 int32_t x1 = 100, y1 = 125, x2 = 350, y2 = 125;
9835
9836 processId(mapper, FIRST_TRACKING_ID);
9837 processPosition(mapper, x1, y1);
9838 processMTSync(mapper);
9839 processId(mapper, SECOND_TRACKING_ID);
9840 processPosition(mapper, x2, y2);
9841 processMTSync(mapper);
9842 processSync(mapper);
9843
9844 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009845 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009846 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009847 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009848 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009849 ASSERT_NO_FATAL_FAILURE(
9850 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9851
9852 // It should be recognized as a SWIPE gesture when two fingers start to move down,
9853 // and there should be 1 pointer.
9854 int32_t movingDistance = 200;
9855 y1 += movingDistance;
9856 y2 += movingDistance;
9857
9858 processId(mapper, FIRST_TRACKING_ID);
9859 processPosition(mapper, x1, y1);
9860 processMTSync(mapper);
9861 processId(mapper, SECOND_TRACKING_ID);
9862 processPosition(mapper, x2, y2);
9863 processMTSync(mapper);
9864 processSync(mapper);
9865
9866 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009867 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009868 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009869 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009870 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009871 // New coordinate is the scaled relative coordinate from the initial coordinate.
9872 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
9873 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9874 0, 0, 0, 0));
9875}
9876
9877/**
9878 * Touch the touch pad with two fingers with a distance wider than the minimum freeform
9879 * gesture width and 1/4 of the diagnal length of the touchpad. Expect to receive
9880 * freeform gestures after two fingers start to move downwards.
9881 */
9882TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthFreeform) {
Harry Cutts33476232023-01-30 19:57:29 +00009883 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +00009884 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009885
9886 NotifyMotionArgs motionArgs;
9887
9888 // Two fingers down at once. Wider than the max swipe width.
9889 // The gesture is expected to be PRESS, then transformed to FREEFORM
9890 int32_t x1 = 100, y1 = 125, x2 = 900, y2 = 125;
9891
9892 processId(mapper, FIRST_TRACKING_ID);
9893 processPosition(mapper, x1, y1);
9894 processMTSync(mapper);
9895 processId(mapper, SECOND_TRACKING_ID);
9896 processPosition(mapper, x2, y2);
9897 processMTSync(mapper);
9898 processSync(mapper);
9899
9900 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009901 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009902 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009903 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009904 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009905 // One pointer for PRESS, and its coordinate is used as the origin for pointer coordinates.
9906 ASSERT_NO_FATAL_FAILURE(
9907 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9908
9909 int32_t movingDistance = 200;
9910
9911 // Move two fingers down, expect a cancel event because gesture is changing to freeform,
9912 // then two down events for two pointers.
9913 y1 += movingDistance;
9914 y2 += movingDistance;
9915
9916 processId(mapper, FIRST_TRACKING_ID);
9917 processPosition(mapper, x1, y1);
9918 processMTSync(mapper);
9919 processId(mapper, SECOND_TRACKING_ID);
9920 processPosition(mapper, x2, y2);
9921 processMTSync(mapper);
9922 processSync(mapper);
9923
9924 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9925 // The previous PRESS gesture is cancelled, because it is transformed to freeform
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009926 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009927 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9928 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009929 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009930 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009931 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
9932 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009933 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009934 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009935 ASSERT_EQ(2U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009936 ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN, motionArgs.action & AMOTION_EVENT_ACTION_MASK);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009937 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009938 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009939 // Two pointers' scaled relative coordinates from their initial centroid.
9940 // Initial y coordinates are 0 as y1 and y2 have the same value.
9941 float cookedX1 = (x1 - x2) / 2 * mPointerXZoomScale;
9942 float cookedX2 = (x2 - x1) / 2 * mPointerXZoomScale;
9943 // When pointers move, the new coordinates equal to the initial coordinates plus
9944 // scaled moving distance.
9945 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
9946 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9947 0, 0, 0, 0));
9948 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], cookedX2,
9949 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9950 0, 0, 0, 0));
9951
9952 // Move two fingers down again, expect one MOVE motion event.
9953 y1 += movingDistance;
9954 y2 += movingDistance;
9955
9956 processId(mapper, FIRST_TRACKING_ID);
9957 processPosition(mapper, x1, y1);
9958 processMTSync(mapper);
9959 processId(mapper, SECOND_TRACKING_ID);
9960 processPosition(mapper, x2, y2);
9961 processMTSync(mapper);
9962 processSync(mapper);
9963
9964 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009965 ASSERT_EQ(2U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009966 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009967 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009968 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009969 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
9970 movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
9971 0, 0, 0, 0, 0));
9972 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], cookedX2,
9973 movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
9974 0, 0, 0, 0, 0));
9975}
9976
Harry Cutts39b7ca22022-10-05 15:55:48 +00009977TEST_F(MultiTouchPointerModeTest, TwoFingerSwipeOffsets) {
Harry Cutts33476232023-01-30 19:57:29 +00009978 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +00009979 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Harry Cutts39b7ca22022-10-05 15:55:48 +00009980 NotifyMotionArgs motionArgs;
9981
9982 // Place two fingers down.
9983 int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125;
9984
9985 processId(mapper, FIRST_TRACKING_ID);
9986 processPosition(mapper, x1, y1);
9987 processMTSync(mapper);
9988 processId(mapper, SECOND_TRACKING_ID);
9989 processPosition(mapper, x2, y2);
9990 processMTSync(mapper);
9991 processSync(mapper);
9992
9993 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009994 ASSERT_EQ(1U, motionArgs.getPointerCount());
Harry Cutts39b7ca22022-10-05 15:55:48 +00009995 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
9996 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
9997 ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET));
9998 ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET));
9999
10000 // Move the two fingers down and to the left.
10001 int32_t movingDistance = 200;
10002 x1 -= movingDistance;
10003 y1 += movingDistance;
10004 x2 -= movingDistance;
10005 y2 += movingDistance;
10006
10007 processId(mapper, FIRST_TRACKING_ID);
10008 processPosition(mapper, x1, y1);
10009 processMTSync(mapper);
10010 processId(mapper, SECOND_TRACKING_ID);
10011 processPosition(mapper, x2, y2);
10012 processMTSync(mapper);
10013 processSync(mapper);
10014
10015 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010016 ASSERT_EQ(1U, motionArgs.getPointerCount());
Harry Cutts39b7ca22022-10-05 15:55:48 +000010017 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
10018 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
10019 ASSERT_LT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET), 0);
10020 ASSERT_GT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET), 0);
10021}
10022
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010023TEST_F(MultiTouchPointerModeTest, WhenViewportActiveStatusChanged_PointerGestureIsReset) {
Harry Cutts33476232023-01-30 19:57:29 +000010024 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010025 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +000010026 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010027 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
10028
10029 // Start a stylus gesture.
10030 processKey(mapper, BTN_TOOL_PEN, 1);
10031 processId(mapper, FIRST_TRACKING_ID);
10032 processPosition(mapper, 100, 200);
10033 processSync(mapper);
10034 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10035 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
10036 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010037 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010038 // TODO(b/257078296): Pointer mode generates extra event.
10039 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10040 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
10041 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010042 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010043 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
10044
10045 // Make the viewport inactive. This will put the device in disabled mode, and the ongoing stylus
10046 // gesture should be disabled.
10047 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
10048 viewport->isActive = false;
10049 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +000010050 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010051 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10052 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
10053 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010054 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010055 // TODO(b/257078296): Pointer mode generates extra event.
10056 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10057 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
10058 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010059 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010060 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
10061}
10062
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010063// --- PeripheralControllerTest ---
Chris Yee2b1e5c2021-03-10 22:45:12 -080010064
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010065class PeripheralControllerTest : public testing::Test {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010066protected:
10067 static const char* DEVICE_NAME;
10068 static const char* DEVICE_LOCATION;
10069 static const int32_t DEVICE_ID;
10070 static const int32_t DEVICE_GENERATION;
10071 static const int32_t DEVICE_CONTROLLER_NUMBER;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010072 static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010073 static const int32_t EVENTHUB_ID;
10074
10075 std::shared_ptr<FakeEventHub> mFakeEventHub;
10076 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010077 std::unique_ptr<TestInputListener> mFakeListener;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010078 std::unique_ptr<InstrumentedInputReader> mReader;
10079 std::shared_ptr<InputDevice> mDevice;
10080
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010081 virtual void SetUp(ftl::Flags<InputDeviceClass> classes) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010082 mFakeEventHub = std::make_unique<FakeEventHub>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010083 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010084 mFakeListener = std::make_unique<TestInputListener>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010085 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010086 *mFakeListener);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010087 mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes);
10088 }
10089
10090 void SetUp() override { SetUp(DEVICE_CLASSES); }
10091
10092 void TearDown() override {
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010093 mFakeListener.reset();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010094 mFakePolicy.clear();
10095 }
10096
Chris Yee2b1e5c2021-03-10 22:45:12 -080010097 std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
10098 const std::string& location, int32_t eventHubId,
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010099 ftl::Flags<InputDeviceClass> classes) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010100 InputDeviceIdentifier identifier;
10101 identifier.name = name;
10102 identifier.location = location;
10103 std::shared_ptr<InputDevice> device =
10104 std::make_shared<InputDevice>(mReader->getContext(), deviceId, DEVICE_GENERATION,
10105 identifier);
10106 mReader->pushNextDevice(device);
10107 mFakeEventHub->addDevice(eventHubId, name, classes);
10108 mReader->loopOnce();
10109 return device;
10110 }
10111
10112 template <class T, typename... Args>
10113 T& addControllerAndConfigure(Args... args) {
10114 T& controller = mDevice->addController<T>(EVENTHUB_ID, args...);
10115
10116 return controller;
10117 }
10118};
10119
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010120const char* PeripheralControllerTest::DEVICE_NAME = "device";
10121const char* PeripheralControllerTest::DEVICE_LOCATION = "BLUETOOTH";
10122const int32_t PeripheralControllerTest::DEVICE_ID = END_RESERVED_ID + 1000;
10123const int32_t PeripheralControllerTest::DEVICE_GENERATION = 2;
10124const int32_t PeripheralControllerTest::DEVICE_CONTROLLER_NUMBER = 0;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010125const ftl::Flags<InputDeviceClass> PeripheralControllerTest::DEVICE_CLASSES =
10126 ftl::Flags<InputDeviceClass>(0); // not needed for current tests
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010127const int32_t PeripheralControllerTest::EVENTHUB_ID = 1;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010128
10129// --- BatteryControllerTest ---
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010130class BatteryControllerTest : public PeripheralControllerTest {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010131protected:
10132 void SetUp() override {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010133 PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::BATTERY);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010134 }
10135};
10136
10137TEST_F(BatteryControllerTest, GetBatteryCapacity) {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010138 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010139
Harry Cuttsa5b71292022-11-28 12:56:17 +000010140 ASSERT_TRUE(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY));
10141 ASSERT_EQ(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY).value_or(-1),
10142 FakeEventHub::BATTERY_CAPACITY);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010143}
10144
10145TEST_F(BatteryControllerTest, GetBatteryStatus) {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010146 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010147
Harry Cuttsa5b71292022-11-28 12:56:17 +000010148 ASSERT_TRUE(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY));
10149 ASSERT_EQ(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY).value_or(-1),
10150 FakeEventHub::BATTERY_STATUS);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010151}
10152
10153// --- LightControllerTest ---
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010154class LightControllerTest : public PeripheralControllerTest {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010155protected:
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010156 void SetUp() override {
10157 PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::LIGHT);
10158 }
Chris Yee2b1e5c2021-03-10 22:45:12 -080010159};
10160
Chris Ye85758332021-05-16 23:05:17 -070010161TEST_F(LightControllerTest, MonoLight) {
10162 RawLightInfo infoMono = {.id = 1,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010163 .name = "mono_light",
Chris Ye85758332021-05-16 23:05:17 -070010164 .maxBrightness = 255,
10165 .flags = InputLightClass::BRIGHTNESS,
10166 .path = ""};
10167 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010168
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010169 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010170 InputDeviceInfo info;
10171 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010172 std::vector<InputDeviceLightInfo> lights = info.getLights();
10173 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010174 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10175 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10176
10177 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_BRIGHTNESS));
10178 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_BRIGHTNESS);
10179}
10180
DingYong99f2c3c2023-12-20 15:46:06 +080010181TEST_F(LightControllerTest, MonoKeyboardMuteLight) {
10182 RawLightInfo infoMono = {.id = 1,
10183 .name = "mono_keyboard_mute",
10184 .maxBrightness = 255,
10185 .flags = InputLightClass::BRIGHTNESS |
10186 InputLightClass::KEYBOARD_MIC_MUTE,
10187 .path = ""};
10188 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10189
10190 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10191 std::list<NotifyArgs> unused =
10192 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10193 /*changes=*/{});
10194
10195 InputDeviceInfo info;
10196 controller.populateDeviceInfo(&info);
10197 std::vector<InputDeviceLightInfo> lights = info.getLights();
10198 ASSERT_EQ(1U, lights.size());
10199 ASSERT_EQ(InputDeviceLightType::KEYBOARD_MIC_MUTE, lights[0].type);
10200 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10201}
10202
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010203TEST_F(LightControllerTest, MonoKeyboardBacklight) {
10204 RawLightInfo infoMono = {.id = 1,
10205 .name = "mono_keyboard_backlight",
10206 .maxBrightness = 255,
10207 .flags = InputLightClass::BRIGHTNESS |
10208 InputLightClass::KEYBOARD_BACKLIGHT,
10209 .path = ""};
10210 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10211
10212 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10213 InputDeviceInfo info;
10214 controller.populateDeviceInfo(&info);
10215 std::vector<InputDeviceLightInfo> lights = info.getLights();
10216 ASSERT_EQ(1U, lights.size());
10217 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10218 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010219
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010220 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_BRIGHTNESS));
10221 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_BRIGHTNESS);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010222}
10223
Vaibhav Devmurari16c24192023-05-04 15:20:12 +000010224TEST_F(LightControllerTest, Ignore_MonoLight_WithPreferredBacklightLevels) {
10225 RawLightInfo infoMono = {.id = 1,
10226 .name = "mono_light",
10227 .maxBrightness = 255,
10228 .flags = InputLightClass::BRIGHTNESS,
10229 .path = ""};
10230 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10231 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10232 "0,100,200");
10233
10234 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10235 std::list<NotifyArgs> unused =
10236 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10237 /*changes=*/{});
10238
10239 InputDeviceInfo info;
10240 controller.populateDeviceInfo(&info);
10241 std::vector<InputDeviceLightInfo> lights = info.getLights();
10242 ASSERT_EQ(1U, lights.size());
10243 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10244}
10245
10246TEST_F(LightControllerTest, KeyboardBacklight_WithNoPreferredBacklightLevels) {
10247 RawLightInfo infoMono = {.id = 1,
10248 .name = "mono_keyboard_backlight",
10249 .maxBrightness = 255,
10250 .flags = InputLightClass::BRIGHTNESS |
10251 InputLightClass::KEYBOARD_BACKLIGHT,
10252 .path = ""};
10253 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10254
10255 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10256 std::list<NotifyArgs> unused =
10257 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10258 /*changes=*/{});
10259
10260 InputDeviceInfo info;
10261 controller.populateDeviceInfo(&info);
10262 std::vector<InputDeviceLightInfo> lights = info.getLights();
10263 ASSERT_EQ(1U, lights.size());
10264 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10265}
10266
10267TEST_F(LightControllerTest, KeyboardBacklight_WithPreferredBacklightLevels) {
10268 RawLightInfo infoMono = {.id = 1,
10269 .name = "mono_keyboard_backlight",
10270 .maxBrightness = 255,
10271 .flags = InputLightClass::BRIGHTNESS |
10272 InputLightClass::KEYBOARD_BACKLIGHT,
10273 .path = ""};
10274 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10275 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10276 "0,100,200");
10277
10278 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10279 std::list<NotifyArgs> unused =
10280 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10281 /*changes=*/{});
10282
10283 InputDeviceInfo info;
10284 controller.populateDeviceInfo(&info);
10285 std::vector<InputDeviceLightInfo> lights = info.getLights();
10286 ASSERT_EQ(1U, lights.size());
10287 ASSERT_EQ(3U, lights[0].preferredBrightnessLevels.size());
10288 std::set<BrightnessLevel>::iterator it = lights[0].preferredBrightnessLevels.begin();
10289 ASSERT_EQ(BrightnessLevel(0), *it);
10290 std::advance(it, 1);
10291 ASSERT_EQ(BrightnessLevel(100), *it);
10292 std::advance(it, 1);
10293 ASSERT_EQ(BrightnessLevel(200), *it);
10294}
10295
10296TEST_F(LightControllerTest, KeyboardBacklight_WithWrongPreferredBacklightLevels) {
10297 RawLightInfo infoMono = {.id = 1,
10298 .name = "mono_keyboard_backlight",
10299 .maxBrightness = 255,
10300 .flags = InputLightClass::BRIGHTNESS |
10301 InputLightClass::KEYBOARD_BACKLIGHT,
10302 .path = ""};
10303 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10304 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10305 "0,100,200,300,400,500");
10306
10307 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10308 std::list<NotifyArgs> unused =
10309 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10310 /*changes=*/{});
10311
10312 InputDeviceInfo info;
10313 controller.populateDeviceInfo(&info);
10314 std::vector<InputDeviceLightInfo> lights = info.getLights();
10315 ASSERT_EQ(1U, lights.size());
10316 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10317}
10318
Chris Yee2b1e5c2021-03-10 22:45:12 -080010319TEST_F(LightControllerTest, RGBLight) {
10320 RawLightInfo infoRed = {.id = 1,
10321 .name = "red",
10322 .maxBrightness = 255,
10323 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED,
10324 .path = ""};
10325 RawLightInfo infoGreen = {.id = 2,
10326 .name = "green",
10327 .maxBrightness = 255,
10328 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN,
10329 .path = ""};
10330 RawLightInfo infoBlue = {.id = 3,
10331 .name = "blue",
10332 .maxBrightness = 255,
10333 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE,
10334 .path = ""};
10335 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10336 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10337 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10338
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010339 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010340 InputDeviceInfo info;
10341 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010342 std::vector<InputDeviceLightInfo> lights = info.getLights();
10343 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010344 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10345 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10346 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10347
10348 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10349 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10350}
10351
10352TEST_F(LightControllerTest, CorrectRGBKeyboardBacklight) {
10353 RawLightInfo infoRed = {.id = 1,
10354 .name = "red_keyboard_backlight",
10355 .maxBrightness = 255,
10356 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED |
10357 InputLightClass::KEYBOARD_BACKLIGHT,
10358 .path = ""};
10359 RawLightInfo infoGreen = {.id = 2,
10360 .name = "green_keyboard_backlight",
10361 .maxBrightness = 255,
10362 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN |
10363 InputLightClass::KEYBOARD_BACKLIGHT,
10364 .path = ""};
10365 RawLightInfo infoBlue = {.id = 3,
10366 .name = "blue_keyboard_backlight",
10367 .maxBrightness = 255,
10368 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE |
10369 InputLightClass::KEYBOARD_BACKLIGHT,
10370 .path = ""};
10371 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10372 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10373 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10374
10375 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10376 InputDeviceInfo info;
10377 controller.populateDeviceInfo(&info);
10378 std::vector<InputDeviceLightInfo> lights = info.getLights();
10379 ASSERT_EQ(1U, lights.size());
10380 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10381 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10382 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10383
10384 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10385 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10386}
10387
10388TEST_F(LightControllerTest, IncorrectRGBKeyboardBacklight) {
10389 RawLightInfo infoRed = {.id = 1,
10390 .name = "red",
10391 .maxBrightness = 255,
10392 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED,
10393 .path = ""};
10394 RawLightInfo infoGreen = {.id = 2,
10395 .name = "green",
10396 .maxBrightness = 255,
10397 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN,
10398 .path = ""};
10399 RawLightInfo infoBlue = {.id = 3,
10400 .name = "blue",
10401 .maxBrightness = 255,
10402 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE,
10403 .path = ""};
10404 RawLightInfo infoGlobal = {.id = 3,
10405 .name = "global_keyboard_backlight",
10406 .maxBrightness = 255,
10407 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GLOBAL |
10408 InputLightClass::KEYBOARD_BACKLIGHT,
10409 .path = ""};
10410 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10411 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10412 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10413 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoGlobal));
10414
10415 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10416 InputDeviceInfo info;
10417 controller.populateDeviceInfo(&info);
10418 std::vector<InputDeviceLightInfo> lights = info.getLights();
10419 ASSERT_EQ(1U, lights.size());
10420 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10421 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10422 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010423
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010424 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10425 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010426}
10427
10428TEST_F(LightControllerTest, MultiColorRGBLight) {
10429 RawLightInfo infoColor = {.id = 1,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010430 .name = "multi_color",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010431 .maxBrightness = 255,
10432 .flags = InputLightClass::BRIGHTNESS |
10433 InputLightClass::MULTI_INTENSITY |
10434 InputLightClass::MULTI_INDEX,
10435 .path = ""};
10436
10437 mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
10438
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010439 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010440 InputDeviceInfo info;
10441 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010442 std::vector<InputDeviceLightInfo> lights = info.getLights();
10443 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010444 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10445 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10446 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10447
10448 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10449 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10450}
10451
10452TEST_F(LightControllerTest, MultiColorRGBKeyboardBacklight) {
10453 RawLightInfo infoColor = {.id = 1,
10454 .name = "multi_color_keyboard_backlight",
10455 .maxBrightness = 255,
10456 .flags = InputLightClass::BRIGHTNESS |
10457 InputLightClass::MULTI_INTENSITY |
10458 InputLightClass::MULTI_INDEX |
10459 InputLightClass::KEYBOARD_BACKLIGHT,
10460 .path = ""};
10461
10462 mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
10463
10464 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10465 InputDeviceInfo info;
10466 controller.populateDeviceInfo(&info);
10467 std::vector<InputDeviceLightInfo> lights = info.getLights();
10468 ASSERT_EQ(1U, lights.size());
10469 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10470 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10471 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010472
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010473 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10474 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010475}
10476
Josep del Rioa1046a82023-08-24 19:57:27 +000010477TEST_F(LightControllerTest, SonyPlayerIdLight) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010478 RawLightInfo info1 = {.id = 1,
Josep del Rioa1046a82023-08-24 19:57:27 +000010479 .name = "sony1",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010480 .maxBrightness = 255,
10481 .flags = InputLightClass::BRIGHTNESS,
10482 .path = ""};
10483 RawLightInfo info2 = {.id = 2,
Josep del Rioa1046a82023-08-24 19:57:27 +000010484 .name = "sony2",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010485 .maxBrightness = 255,
10486 .flags = InputLightClass::BRIGHTNESS,
10487 .path = ""};
10488 RawLightInfo info3 = {.id = 3,
Josep del Rioa1046a82023-08-24 19:57:27 +000010489 .name = "sony3",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010490 .maxBrightness = 255,
10491 .flags = InputLightClass::BRIGHTNESS,
10492 .path = ""};
10493 RawLightInfo info4 = {.id = 4,
Josep del Rioa1046a82023-08-24 19:57:27 +000010494 .name = "sony4",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010495 .maxBrightness = 255,
10496 .flags = InputLightClass::BRIGHTNESS,
10497 .path = ""};
10498 mFakeEventHub->addRawLightInfo(info1.id, std::move(info1));
10499 mFakeEventHub->addRawLightInfo(info2.id, std::move(info2));
10500 mFakeEventHub->addRawLightInfo(info3.id, std::move(info3));
10501 mFakeEventHub->addRawLightInfo(info4.id, std::move(info4));
10502
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010503 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010504 InputDeviceInfo info;
10505 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010506 std::vector<InputDeviceLightInfo> lights = info.getLights();
10507 ASSERT_EQ(1U, lights.size());
Josep del Rioa1046a82023-08-24 19:57:27 +000010508 ASSERT_STREQ("sony", lights[0].name.c_str());
10509 ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
10510 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10511 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10512
10513 ASSERT_FALSE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10514 ASSERT_TRUE(controller.setLightPlayerId(lights[0].id, LIGHT_PLAYER_ID));
10515 ASSERT_EQ(controller.getLightPlayerId(lights[0].id).value_or(-1), LIGHT_PLAYER_ID);
10516 ASSERT_STREQ("sony", lights[0].name.c_str());
10517}
10518
10519TEST_F(LightControllerTest, PlayerIdLight) {
10520 RawLightInfo info1 = {.id = 1,
10521 .name = "player-1",
10522 .maxBrightness = 255,
10523 .flags = InputLightClass::BRIGHTNESS,
10524 .path = ""};
10525 RawLightInfo info2 = {.id = 2,
10526 .name = "player-2",
10527 .maxBrightness = 255,
10528 .flags = InputLightClass::BRIGHTNESS,
10529 .path = ""};
10530 RawLightInfo info3 = {.id = 3,
10531 .name = "player-3",
10532 .maxBrightness = 255,
10533 .flags = InputLightClass::BRIGHTNESS,
10534 .path = ""};
10535 RawLightInfo info4 = {.id = 4,
10536 .name = "player-4",
10537 .maxBrightness = 255,
10538 .flags = InputLightClass::BRIGHTNESS,
10539 .path = ""};
10540 mFakeEventHub->addRawLightInfo(info1.id, std::move(info1));
10541 mFakeEventHub->addRawLightInfo(info2.id, std::move(info2));
10542 mFakeEventHub->addRawLightInfo(info3.id, std::move(info3));
10543 mFakeEventHub->addRawLightInfo(info4.id, std::move(info4));
10544
10545 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10546 InputDeviceInfo info;
10547 controller.populateDeviceInfo(&info);
10548 std::vector<InputDeviceLightInfo> lights = info.getLights();
10549 ASSERT_EQ(1U, lights.size());
10550 ASSERT_STREQ("player", lights[0].name.c_str());
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010551 ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010552 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10553 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010554
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010555 ASSERT_FALSE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10556 ASSERT_TRUE(controller.setLightPlayerId(lights[0].id, LIGHT_PLAYER_ID));
10557 ASSERT_EQ(controller.getLightPlayerId(lights[0].id).value_or(-1), LIGHT_PLAYER_ID);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010558}
10559
Michael Wrightd02c5b62014-02-10 15:10:22 -080010560} // namespace android