blob: 48fd717631db9475b3c3933f902060f486da19b1 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Dominik Laskowski2f01d772022-03-23 16:01:29 -070017#include <cinttypes>
18#include <memory>
Harry Cuttsf13161a2023-03-08 14:15:49 +000019#include <optional>
Dominik Laskowski2f01d772022-03-23 16:01:29 -070020
Prabir Pradhan2770d242019-09-02 18:07:11 -070021#include <CursorInputMapper.h>
22#include <InputDevice.h>
23#include <InputMapper.h>
24#include <InputReader.h>
Prabir Pradhan1aed8582019-12-30 11:46:51 -080025#include <InputReaderBase.h>
26#include <InputReaderFactory.h>
Prabir Pradhan2770d242019-09-02 18:07:11 -070027#include <KeyboardInputMapper.h>
28#include <MultiTouchInputMapper.h>
Prabir Pradhan018faea2024-05-08 21:52:54 +000029#include <NotifyArgsBuilders.h>
Chris Ye1dd2e5c2021-04-04 23:12:41 -070030#include <PeripheralController.h>
Chris Yef59a2f42020-10-16 12:55:26 -070031#include <SensorInputMapper.h>
Prabir Pradhan2770d242019-09-02 18:07:11 -070032#include <SingleTouchInputMapper.h>
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000033#include <TestEventMatchers.h>
Prabir Pradhan2770d242019-09-02 18:07:11 -070034#include <TestInputListener.h>
35#include <TouchInputMapper.h>
Prabir Pradhan1aed8582019-12-30 11:46:51 -080036#include <UinputDevice.h>
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070037#include <android-base/thread_annotations.h>
Byoungho Jungda10dd32023-10-06 17:03:45 +090038#include <com_android_input_flags.h>
Michael Wrighta9cf4192022-12-01 23:46:39 +000039#include <ftl/enum.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080040#include <gtest/gtest.h>
Michael Wrighta9cf4192022-12-01 23:46:39 +000041#include <ui/Rotation.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080042
Siarhei Vishniakou21e96e62022-10-27 10:23:37 -070043#include <thread>
Harry Cuttsa5b71292022-11-28 12:56:17 +000044#include "FakeEventHub.h"
Harry Cutts6b5fbc52022-11-28 16:37:43 +000045#include "FakeInputReaderPolicy.h"
Harry Cuttse6512e12022-11-28 18:44:01 +000046#include "InputMapperTest.h"
Harry Cutts144ff542022-11-28 17:41:06 +000047#include "InstrumentedInputReader.h"
Harry Cuttsa5b71292022-11-28 12:56:17 +000048#include "TestConstants.h"
Michael Wrightdde67b82020-10-27 16:09:22 +000049#include "input/DisplayViewport.h"
50#include "input/Input.h"
Michael Wright17db18e2020-06-26 20:51:44 +010051
Michael Wrightd02c5b62014-02-10 15:10:22 -080052namespace android {
53
Dominik Laskowski2f01d772022-03-23 16:01:29 -070054using namespace ftl::flag_operators;
Prabir Pradhan739dca42022-09-09 20:12:01 +000055using testing::AllOf;
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +000056using testing::VariantWith;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070057using std::chrono_literals::operator""ms;
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -080058using std::chrono_literals::operator""s;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070059
Michael Wrightd02c5b62014-02-10 15:10:22 -080060// Arbitrary display properties.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070061static constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhanc13ff082022-09-08 22:03:30 +000062static const std::string DISPLAY_UNIQUE_ID = "local:1";
Linnan Li13bf76a2024-05-05 19:18:02 +080063static constexpr ui::LogicalDisplayId SECONDARY_DISPLAY_ID =
64 ui::LogicalDisplayId{DISPLAY_ID.val() + 1};
arthurhungcc7f9802020-04-30 17:55:40 +080065static constexpr int32_t DISPLAY_WIDTH = 480;
66static constexpr int32_t DISPLAY_HEIGHT = 800;
Linnan Li13bf76a2024-05-05 19:18:02 +080067static constexpr ui::LogicalDisplayId VIRTUAL_DISPLAY_ID = ui::LogicalDisplayId{1};
arthurhungcc7f9802020-04-30 17:55:40 +080068static constexpr int32_t VIRTUAL_DISPLAY_WIDTH = 400;
69static constexpr int32_t VIRTUAL_DISPLAY_HEIGHT = 500;
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -070070static const char* VIRTUAL_DISPLAY_UNIQUE_ID = "virtual:1";
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -070071static constexpr std::optional<uint8_t> NO_PORT = std::nullopt; // no physical port is specified
Michael Wrightd02c5b62014-02-10 15:10:22 -080072
arthurhungcc7f9802020-04-30 17:55:40 +080073static constexpr int32_t FIRST_SLOT = 0;
74static constexpr int32_t SECOND_SLOT = 1;
75static constexpr int32_t THIRD_SLOT = 2;
76static constexpr int32_t INVALID_TRACKING_ID = -1;
77static constexpr int32_t FIRST_TRACKING_ID = 0;
78static constexpr int32_t SECOND_TRACKING_ID = 1;
79static constexpr int32_t THIRD_TRACKING_ID = 2;
Chris Ye3fdbfef2021-01-06 18:45:18 -080080static constexpr int32_t LIGHT_BRIGHTNESS = 0x55000000;
81static constexpr int32_t LIGHT_COLOR = 0x7F448866;
82static constexpr int32_t LIGHT_PLAYER_ID = 2;
arthurhungcc7f9802020-04-30 17:55:40 +080083
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -080084static constexpr int32_t ACTION_POINTER_0_DOWN =
85 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
86static constexpr int32_t ACTION_POINTER_0_UP =
87 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
88static constexpr int32_t ACTION_POINTER_1_DOWN =
89 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
90static constexpr int32_t ACTION_POINTER_1_UP =
91 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
92
Prabir Pradhanb08a0e82023-09-14 22:28:32 +000093static constexpr uint32_t STYLUS_FUSION_SOURCE =
94 AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_BLUETOOTH_STYLUS;
95
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +000096// Minimum timestamp separation between subsequent input events from a Bluetooth device.
97static constexpr nsecs_t MIN_BLUETOOTH_TIMESTAMP_DELTA = ms2ns(4);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +000098
Byoungho Jungda10dd32023-10-06 17:03:45 +090099namespace input_flags = com::android::input::flags;
100
Michael Wrightd02c5b62014-02-10 15:10:22 -0800101template<typename T>
102static inline T min(T a, T b) {
103 return a < b ? a : b;
104}
105
106static inline float avg(float x, float y) {
107 return (x + y) / 2;
108}
109
Chris Ye3fdbfef2021-01-06 18:45:18 -0800110// Mapping for light color name and the light color
111const std::unordered_map<std::string, LightColor> LIGHT_COLORS = {{"red", LightColor::RED},
112 {"green", LightColor::GREEN},
113 {"blue", LightColor::BLUE}};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800114
Michael Wrighta9cf4192022-12-01 23:46:39 +0000115static ui::Rotation getInverseRotation(ui::Rotation orientation) {
Prabir Pradhanc14266f2021-05-12 15:56:24 -0700116 switch (orientation) {
Michael Wrighta9cf4192022-12-01 23:46:39 +0000117 case ui::ROTATION_90:
118 return ui::ROTATION_270;
119 case ui::ROTATION_270:
120 return ui::ROTATION_90;
Prabir Pradhanc14266f2021-05-12 15:56:24 -0700121 default:
122 return orientation;
123 }
124}
125
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800126static void assertAxisResolution(MultiTouchInputMapper& mapper, int axis, float resolution) {
127 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +0000128 mapper.populateDeviceInfo(info);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800129
130 const InputDeviceInfo::MotionRange* motionRange =
131 info.getMotionRange(axis, AINPUT_SOURCE_TOUCHSCREEN);
132 ASSERT_NEAR(motionRange->resolution, resolution, EPSILON);
133}
134
135static void assertAxisNotPresent(MultiTouchInputMapper& mapper, int axis) {
136 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +0000137 mapper.populateDeviceInfo(info);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800138
139 const InputDeviceInfo::MotionRange* motionRange =
140 info.getMotionRange(axis, AINPUT_SOURCE_TOUCHSCREEN);
141 ASSERT_EQ(nullptr, motionRange);
142}
143
Siarhei Vishniakou21e96e62022-10-27 10:23:37 -0700144[[maybe_unused]] static void dumpReader(InputReader& reader) {
145 std::string dump;
146 reader.dump(dump);
147 std::istringstream iss(dump);
148 for (std::string line; std::getline(iss, line);) {
149 ALOGE("%s", line.c_str());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -0800150 std::this_thread::sleep_for(1ms);
Siarhei Vishniakou21e96e62022-10-27 10:23:37 -0700151 }
152}
153
Michael Wrightd02c5b62014-02-10 15:10:22 -0800154// --- FakeInputMapper ---
155
156class FakeInputMapper : public InputMapper {
157 uint32_t mSources;
158 int32_t mKeyboardType;
159 int32_t mMetaState;
160 KeyedVector<int32_t, int32_t> mKeyCodeStates;
161 KeyedVector<int32_t, int32_t> mScanCodeStates;
162 KeyedVector<int32_t, int32_t> mSwitchStates;
Philip Junker4af3b3d2021-12-14 10:36:55 +0100163 // fake mapping which would normally come from keyCharacterMap
164 std::unordered_map<int32_t, int32_t> mKeyCodeMapping;
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800165 std::vector<int32_t> mSupportedKeyCodes;
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700166 std::list<NotifyArgs> mProcessResult;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800167
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700168 std::mutex mLock;
169 std::condition_variable mStateChangedCondition;
170 bool mConfigureWasCalled GUARDED_BY(mLock);
171 bool mResetWasCalled GUARDED_BY(mLock);
172 bool mProcessWasCalled GUARDED_BY(mLock);
173 RawEvent mLastEvent GUARDED_BY(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800174
Arthur Hungc23540e2018-11-29 20:42:11 +0800175 std::optional<DisplayViewport> mViewport;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800176public:
Arpit Singh8e6fb252023-04-06 11:49:17 +0000177 FakeInputMapper(InputDeviceContext& deviceContext, const InputReaderConfiguration& readerConfig,
178 uint32_t sources)
179 : InputMapper(deviceContext, readerConfig),
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800180 mSources(sources),
181 mKeyboardType(AINPUT_KEYBOARD_TYPE_NONE),
Michael Wrightd02c5b62014-02-10 15:10:22 -0800182 mMetaState(0),
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800183 mConfigureWasCalled(false),
184 mResetWasCalled(false),
185 mProcessWasCalled(false) {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800186
Chris Yea52ade12020-08-27 16:49:20 -0700187 virtual ~FakeInputMapper() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800188
189 void setKeyboardType(int32_t keyboardType) {
190 mKeyboardType = keyboardType;
191 }
192
193 void setMetaState(int32_t metaState) {
194 mMetaState = metaState;
195 }
196
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700197 // Sets the return value for the `process` call.
198 void setProcessResult(std::list<NotifyArgs> notifyArgs) {
199 mProcessResult.clear();
200 for (auto notifyArg : notifyArgs) {
201 mProcessResult.push_back(notifyArg);
202 }
203 }
204
Michael Wrightd02c5b62014-02-10 15:10:22 -0800205 void assertConfigureWasCalled() {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700206 std::unique_lock<std::mutex> lock(mLock);
207 base::ScopedLockAssertion assumeLocked(mLock);
208 const bool configureCalled =
209 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
210 return mConfigureWasCalled;
211 });
212 if (!configureCalled) {
213 FAIL() << "Expected configure() to have been called.";
214 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800215 mConfigureWasCalled = false;
216 }
217
218 void assertResetWasCalled() {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700219 std::unique_lock<std::mutex> lock(mLock);
220 base::ScopedLockAssertion assumeLocked(mLock);
221 const bool resetCalled =
222 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
223 return mResetWasCalled;
224 });
225 if (!resetCalled) {
226 FAIL() << "Expected reset() to have been called.";
227 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800228 mResetWasCalled = false;
229 }
230
Prabir Pradhanf8d9e442023-12-06 22:06:13 +0000231 void assertResetWasNotCalled() {
232 std::scoped_lock lock(mLock);
233 ASSERT_FALSE(mResetWasCalled) << "Expected reset to not have been called.";
234 }
235
Yi Kong9b14ac62018-07-17 13:48:38 -0700236 void assertProcessWasCalled(RawEvent* outLastEvent = nullptr) {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700237 std::unique_lock<std::mutex> lock(mLock);
238 base::ScopedLockAssertion assumeLocked(mLock);
239 const bool processCalled =
240 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
241 return mProcessWasCalled;
242 });
243 if (!processCalled) {
244 FAIL() << "Expected process() to have been called.";
245 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800246 if (outLastEvent) {
247 *outLastEvent = mLastEvent;
248 }
249 mProcessWasCalled = false;
250 }
251
Prabir Pradhanf8d9e442023-12-06 22:06:13 +0000252 void assertProcessWasNotCalled() {
253 std::scoped_lock lock(mLock);
254 ASSERT_FALSE(mProcessWasCalled) << "Expected process to not have been called.";
255 }
256
Michael Wrightd02c5b62014-02-10 15:10:22 -0800257 void setKeyCodeState(int32_t keyCode, int32_t state) {
258 mKeyCodeStates.replaceValueFor(keyCode, state);
259 }
260
261 void setScanCodeState(int32_t scanCode, int32_t state) {
262 mScanCodeStates.replaceValueFor(scanCode, state);
263 }
264
265 void setSwitchState(int32_t switchCode, int32_t state) {
266 mSwitchStates.replaceValueFor(switchCode, state);
267 }
268
269 void addSupportedKeyCode(int32_t keyCode) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800270 mSupportedKeyCodes.push_back(keyCode);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800271 }
272
Philip Junker4af3b3d2021-12-14 10:36:55 +0100273 void addKeyCodeMapping(int32_t fromKeyCode, int32_t toKeyCode) {
274 mKeyCodeMapping.insert_or_assign(fromKeyCode, toKeyCode);
275 }
276
Michael Wrightd02c5b62014-02-10 15:10:22 -0800277private:
Philip Junker4af3b3d2021-12-14 10:36:55 +0100278 uint32_t getSources() const override { return mSources; }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800279
Harry Cuttsd02ea102023-03-17 18:21:30 +0000280 void populateDeviceInfo(InputDeviceInfo& deviceInfo) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800281 InputMapper::populateDeviceInfo(deviceInfo);
282
283 if (mKeyboardType != AINPUT_KEYBOARD_TYPE_NONE) {
Harry Cuttsd02ea102023-03-17 18:21:30 +0000284 deviceInfo.setKeyboardType(mKeyboardType);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800285 }
286 }
287
Arpit Singhed6c3de2023-04-05 19:24:37 +0000288 std::list<NotifyArgs> reconfigure(nsecs_t, const InputReaderConfiguration& config,
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000289 ConfigurationChanges changes) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700290 std::scoped_lock<std::mutex> lock(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800291 mConfigureWasCalled = true;
Arthur Hungc23540e2018-11-29 20:42:11 +0800292
293 // Find the associated viewport if exist.
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800294 const std::optional<uint8_t> displayPort = getDeviceContext().getAssociatedDisplayPort();
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000295 if (displayPort && changes.test(InputReaderConfiguration::Change::DISPLAY_INFO)) {
Arpit Singhed6c3de2023-04-05 19:24:37 +0000296 mViewport = config.getDisplayViewportByPort(*displayPort);
Arthur Hungc23540e2018-11-29 20:42:11 +0800297 }
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700298
299 mStateChangedCondition.notify_all();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700300 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800301 }
302
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700303 std::list<NotifyArgs> reset(nsecs_t) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700304 std::scoped_lock<std::mutex> lock(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800305 mResetWasCalled = true;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700306 mStateChangedCondition.notify_all();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700307 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800308 }
309
Harry Cuttsa32a1192024-06-04 15:10:31 +0000310 std::list<NotifyArgs> process(const RawEvent& rawEvent) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700311 std::scoped_lock<std::mutex> lock(mLock);
Harry Cuttsa32a1192024-06-04 15:10:31 +0000312 mLastEvent = rawEvent;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800313 mProcessWasCalled = true;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700314 mStateChangedCondition.notify_all();
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700315 return mProcessResult;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800316 }
317
Chris Yea52ade12020-08-27 16:49:20 -0700318 int32_t getKeyCodeState(uint32_t, int32_t keyCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800319 ssize_t index = mKeyCodeStates.indexOfKey(keyCode);
320 return index >= 0 ? mKeyCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
321 }
322
Philip Junker4af3b3d2021-12-14 10:36:55 +0100323 int32_t getKeyCodeForKeyLocation(int32_t locationKeyCode) const override {
324 auto it = mKeyCodeMapping.find(locationKeyCode);
325 return it != mKeyCodeMapping.end() ? it->second : locationKeyCode;
326 }
327
Chris Yea52ade12020-08-27 16:49:20 -0700328 int32_t getScanCodeState(uint32_t, int32_t scanCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800329 ssize_t index = mScanCodeStates.indexOfKey(scanCode);
330 return index >= 0 ? mScanCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
331 }
332
Chris Yea52ade12020-08-27 16:49:20 -0700333 int32_t getSwitchState(uint32_t, int32_t switchCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800334 ssize_t index = mSwitchStates.indexOfKey(switchCode);
335 return index >= 0 ? mSwitchStates.valueAt(index) : AKEY_STATE_UNKNOWN;
336 }
337
Chris Yea52ade12020-08-27 16:49:20 -0700338 // Return true if the device has non-empty key layout.
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700339 bool markSupportedKeyCodes(uint32_t, const std::vector<int32_t>& keyCodes,
Chris Yea52ade12020-08-27 16:49:20 -0700340 uint8_t* outFlags) override {
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700341 for (size_t i = 0; i < keyCodes.size(); i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800342 for (size_t j = 0; j < mSupportedKeyCodes.size(); j++) {
343 if (keyCodes[i] == mSupportedKeyCodes[j]) {
344 outFlags[i] = 1;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800345 }
346 }
347 }
Chris Yea52ade12020-08-27 16:49:20 -0700348 bool result = mSupportedKeyCodes.size() > 0;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800349 return result;
350 }
351
352 virtual int32_t getMetaState() {
353 return mMetaState;
354 }
355
356 virtual void fadePointer() {
357 }
Arthur Hungc23540e2018-11-29 20:42:11 +0800358
Linnan Li13bf76a2024-05-05 19:18:02 +0800359 virtual std::optional<ui::LogicalDisplayId> getAssociatedDisplay() {
Arthur Hungc23540e2018-11-29 20:42:11 +0800360 if (mViewport) {
361 return std::make_optional(mViewport->displayId);
362 }
363 return std::nullopt;
364 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800365};
366
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700367// --- InputReaderPolicyTest ---
368class InputReaderPolicyTest : public testing::Test {
Siarhei Vishniakoucd7ac1e2018-10-15 13:39:50 -0700369protected:
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700370 sp<FakeInputReaderPolicy> mFakePolicy;
371
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700372 void SetUp() override { mFakePolicy = sp<FakeInputReaderPolicy>::make(); }
Chris Yea52ade12020-08-27 16:49:20 -0700373 void TearDown() override { mFakePolicy.clear(); }
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700374};
375
376/**
377 * Check that empty set of viewports is an acceptable configuration.
378 * Also try to get internal viewport two different ways - by type and by uniqueId.
379 *
380 * There will be confusion if two viewports with empty uniqueId and identical type are present.
381 * Such configuration is not currently allowed.
382 */
383TEST_F(InputReaderPolicyTest, Viewports_GetCleared) {
Siarhei Vishniakoucd7ac1e2018-10-15 13:39:50 -0700384 static const std::string uniqueId = "local:0";
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700385
386 // We didn't add any viewports yet, so there shouldn't be any.
387 std::optional<DisplayViewport> internalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100388 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700389 ASSERT_FALSE(internalViewport);
390
391 // Add an internal viewport, then clear it
Michael Wrighta9cf4192022-12-01 23:46:39 +0000392 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000393 /*isActive=*/true, uniqueId, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700394
395 // Check matching by uniqueId
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700396 internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700397 ASSERT_TRUE(internalViewport);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100398 ASSERT_EQ(ViewportType::INTERNAL, internalViewport->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700399
400 // Check matching by viewport type
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100401 internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700402 ASSERT_TRUE(internalViewport);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700403 ASSERT_EQ(uniqueId, internalViewport->uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700404
405 mFakePolicy->clearViewports();
406 // Make sure nothing is found after clear
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700407 internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700408 ASSERT_FALSE(internalViewport);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100409 internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700410 ASSERT_FALSE(internalViewport);
411}
412
413TEST_F(InputReaderPolicyTest, Viewports_GetByType) {
414 const std::string internalUniqueId = "local:0";
415 const std::string externalUniqueId = "local:1";
416 const std::string virtualUniqueId1 = "virtual:2";
417 const std::string virtualUniqueId2 = "virtual:3";
Linnan Li13bf76a2024-05-05 19:18:02 +0800418 constexpr ui::LogicalDisplayId virtualDisplayId1 = ui::LogicalDisplayId{2};
419 constexpr ui::LogicalDisplayId virtualDisplayId2 = ui::LogicalDisplayId{3};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700420
421 // Add an internal viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000422 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000423 /*isActive=*/true, internalUniqueId, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000424 ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700425 // Add an external viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000426 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000427 /*isActive=*/true, externalUniqueId, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000428 ViewportType::EXTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700429 // Add an virtual viewport
430 mFakePolicy->addDisplayViewport(virtualDisplayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000431 ui::ROTATION_0, /*isActive=*/true, virtualUniqueId1, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000432 ViewportType::VIRTUAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700433 // Add another virtual viewport
434 mFakePolicy->addDisplayViewport(virtualDisplayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000435 ui::ROTATION_0, /*isActive=*/true, virtualUniqueId2, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000436 ViewportType::VIRTUAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700437
438 // Check matching by type for internal
439 std::optional<DisplayViewport> internalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100440 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700441 ASSERT_TRUE(internalViewport);
442 ASSERT_EQ(internalUniqueId, internalViewport->uniqueId);
443
444 // Check matching by type for external
445 std::optional<DisplayViewport> externalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100446 mFakePolicy->getDisplayViewportByType(ViewportType::EXTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700447 ASSERT_TRUE(externalViewport);
448 ASSERT_EQ(externalUniqueId, externalViewport->uniqueId);
449
450 // Check matching by uniqueId for virtual viewport #1
451 std::optional<DisplayViewport> virtualViewport1 =
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700452 mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId1);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700453 ASSERT_TRUE(virtualViewport1);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100454 ASSERT_EQ(ViewportType::VIRTUAL, virtualViewport1->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700455 ASSERT_EQ(virtualUniqueId1, virtualViewport1->uniqueId);
456 ASSERT_EQ(virtualDisplayId1, virtualViewport1->displayId);
457
458 // Check matching by uniqueId for virtual viewport #2
459 std::optional<DisplayViewport> virtualViewport2 =
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700460 mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId2);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700461 ASSERT_TRUE(virtualViewport2);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100462 ASSERT_EQ(ViewportType::VIRTUAL, virtualViewport2->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700463 ASSERT_EQ(virtualUniqueId2, virtualViewport2->uniqueId);
464 ASSERT_EQ(virtualDisplayId2, virtualViewport2->displayId);
465}
466
467
468/**
469 * We can have 2 viewports of the same kind. We can distinguish them by uniqueId, and confirm
470 * that lookup works by checking display id.
471 * Check that 2 viewports of each kind is possible, for all existing viewport types.
472 */
473TEST_F(InputReaderPolicyTest, Viewports_TwoOfSameType) {
474 const std::string uniqueId1 = "uniqueId1";
475 const std::string uniqueId2 = "uniqueId2";
Linnan Li13bf76a2024-05-05 19:18:02 +0800476 constexpr ui::LogicalDisplayId displayId1 = ui::LogicalDisplayId{2};
477 constexpr ui::LogicalDisplayId displayId2 = ui::LogicalDisplayId{3};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700478
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100479 std::vector<ViewportType> types = {ViewportType::INTERNAL, ViewportType::EXTERNAL,
480 ViewportType::VIRTUAL};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700481 for (const ViewportType& type : types) {
482 mFakePolicy->clearViewports();
483 // Add a viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000484 mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000485 /*isActive=*/true, uniqueId1, NO_PORT, type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700486 // Add another viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000487 mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000488 /*isActive=*/true, uniqueId2, NO_PORT, type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700489
490 // Check that correct display viewport was returned by comparing the display IDs.
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700491 std::optional<DisplayViewport> viewport1 =
492 mFakePolicy->getDisplayViewportByUniqueId(uniqueId1);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700493 ASSERT_TRUE(viewport1);
494 ASSERT_EQ(displayId1, viewport1->displayId);
495 ASSERT_EQ(type, viewport1->type);
496
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700497 std::optional<DisplayViewport> viewport2 =
498 mFakePolicy->getDisplayViewportByUniqueId(uniqueId2);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700499 ASSERT_TRUE(viewport2);
500 ASSERT_EQ(displayId2, viewport2->displayId);
501 ASSERT_EQ(type, viewport2->type);
502
503 // When there are multiple viewports of the same kind, and uniqueId is not specified
504 // in the call to getDisplayViewport, then that situation is not supported.
505 // The viewports can be stored in any order, so we cannot rely on the order, since that
506 // is just implementation detail.
507 // However, we can check that it still returns *a* viewport, we just cannot assert
508 // which one specifically is returned.
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700509 std::optional<DisplayViewport> someViewport = mFakePolicy->getDisplayViewportByType(type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700510 ASSERT_TRUE(someViewport);
511 }
512}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800513
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700514/**
Michael Wrightdde67b82020-10-27 16:09:22 +0000515 * When we have multiple internal displays make sure we always return the default display when
516 * querying by type.
517 */
518TEST_F(InputReaderPolicyTest, Viewports_ByTypeReturnsDefaultForInternal) {
519 const std::string uniqueId1 = "uniqueId1";
520 const std::string uniqueId2 = "uniqueId2";
Linnan Li13bf76a2024-05-05 19:18:02 +0800521 constexpr ui::LogicalDisplayId nonDefaultDisplayId = ui::LogicalDisplayId{2};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700522 ASSERT_NE(nonDefaultDisplayId, ui::LogicalDisplayId::DEFAULT)
523 << "Test display ID should not be ui::LogicalDisplayId::DEFAULT ";
Michael Wrightdde67b82020-10-27 16:09:22 +0000524
525 // Add the default display first and ensure it gets returned.
526 mFakePolicy->clearViewports();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700527 mFakePolicy->addDisplayViewport(ui::LogicalDisplayId::DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000528 ui::ROTATION_0, /*isActive=*/true, uniqueId1, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000529 ViewportType::INTERNAL);
530 mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000531 ui::ROTATION_0, /*isActive=*/true, uniqueId2, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000532 ViewportType::INTERNAL);
533
534 std::optional<DisplayViewport> viewport =
535 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
536 ASSERT_TRUE(viewport);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700537 ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, viewport->displayId);
Michael Wrightdde67b82020-10-27 16:09:22 +0000538 ASSERT_EQ(ViewportType::INTERNAL, viewport->type);
539
540 // Add the default display second to make sure order doesn't matter.
541 mFakePolicy->clearViewports();
542 mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000543 ui::ROTATION_0, /*isActive=*/true, uniqueId2, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000544 ViewportType::INTERNAL);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700545 mFakePolicy->addDisplayViewport(ui::LogicalDisplayId::DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000546 ui::ROTATION_0, /*isActive=*/true, uniqueId1, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000547 ViewportType::INTERNAL);
548
549 viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
550 ASSERT_TRUE(viewport);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700551 ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, viewport->displayId);
Michael Wrightdde67b82020-10-27 16:09:22 +0000552 ASSERT_EQ(ViewportType::INTERNAL, viewport->type);
553}
554
555/**
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700556 * Check getDisplayViewportByPort
557 */
558TEST_F(InputReaderPolicyTest, Viewports_GetByPort) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100559 constexpr ViewportType type = ViewportType::EXTERNAL;
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700560 const std::string uniqueId1 = "uniqueId1";
561 const std::string uniqueId2 = "uniqueId2";
Linnan Li13bf76a2024-05-05 19:18:02 +0800562 constexpr ui::LogicalDisplayId displayId1 = ui::LogicalDisplayId{1};
563 constexpr ui::LogicalDisplayId displayId2 = ui::LogicalDisplayId{2};
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700564 const uint8_t hdmi1 = 0;
565 const uint8_t hdmi2 = 1;
566 const uint8_t hdmi3 = 2;
567
568 mFakePolicy->clearViewports();
569 // Add a viewport that's associated with some display port that's not of interest.
Michael Wrighta9cf4192022-12-01 23:46:39 +0000570 mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000571 /*isActive=*/true, uniqueId1, hdmi3, type);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700572 // Add another viewport, connected to HDMI1 port
Michael Wrighta9cf4192022-12-01 23:46:39 +0000573 mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000574 /*isActive=*/true, uniqueId2, hdmi1, type);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700575
576 // Check that correct display viewport was returned by comparing the display ports.
577 std::optional<DisplayViewport> hdmi1Viewport = mFakePolicy->getDisplayViewportByPort(hdmi1);
578 ASSERT_TRUE(hdmi1Viewport);
579 ASSERT_EQ(displayId2, hdmi1Viewport->displayId);
580 ASSERT_EQ(uniqueId2, hdmi1Viewport->uniqueId);
581
582 // Check that we can still get the same viewport using the uniqueId
583 hdmi1Viewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId2);
584 ASSERT_TRUE(hdmi1Viewport);
585 ASSERT_EQ(displayId2, hdmi1Viewport->displayId);
586 ASSERT_EQ(uniqueId2, hdmi1Viewport->uniqueId);
587 ASSERT_EQ(type, hdmi1Viewport->type);
588
589 // Check that we cannot find a port with "HDMI2", because we never added one
590 std::optional<DisplayViewport> hdmi2Viewport = mFakePolicy->getDisplayViewportByPort(hdmi2);
591 ASSERT_FALSE(hdmi2Viewport);
592}
593
Michael Wrightd02c5b62014-02-10 15:10:22 -0800594// --- InputReaderTest ---
595
596class InputReaderTest : public testing::Test {
597protected:
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700598 std::unique_ptr<TestInputListener> mFakeListener;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800599 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou3bc7e092019-07-24 17:43:30 -0700600 std::shared_ptr<FakeEventHub> mFakeEventHub;
Prabir Pradhan28efc192019-11-05 01:10:04 +0000601 std::unique_ptr<InstrumentedInputReader> mReader;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800602
Chris Yea52ade12020-08-27 16:49:20 -0700603 void SetUp() override {
Siarhei Vishniakou3bc7e092019-07-24 17:43:30 -0700604 mFakeEventHub = std::make_unique<FakeEventHub>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700605 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700606 mFakeListener = std::make_unique<TestInputListener>();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800607
Prabir Pradhan28efc192019-11-05 01:10:04 +0000608 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700609 *mFakeListener);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800610 }
611
Chris Yea52ade12020-08-27 16:49:20 -0700612 void TearDown() override {
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700613 mFakeListener.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800614 mFakePolicy.clear();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800615 }
616
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700617 void addDevice(int32_t eventHubId, const std::string& name,
618 ftl::Flags<InputDeviceClass> classes, const PropertyMap* configuration) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800619 mFakeEventHub->addDevice(eventHubId, name, classes);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800620
621 if (configuration) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800622 mFakeEventHub->addConfigurationMap(eventHubId, configuration);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800623 }
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000624 mReader->loopOnce();
625 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700626 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Prabir Pradhane3da4bb2023-04-05 23:51:23 +0000627 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyInputDevicesChangedWasCalled());
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700628 ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800629 }
630
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800631 void disableDevice(int32_t deviceId) {
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700632 mFakePolicy->addDisabledDevice(deviceId);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000633 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::ENABLED_STATE);
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700634 }
635
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800636 void enableDevice(int32_t deviceId) {
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700637 mFakePolicy->removeDisabledDevice(deviceId);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000638 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::ENABLED_STATE);
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700639 }
640
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800641 FakeInputMapper& addDeviceWithFakeInputMapper(int32_t deviceId, int32_t eventHubId,
Chris Ye1b0c7342020-07-28 21:57:03 -0700642 const std::string& name,
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700643 ftl::Flags<InputDeviceClass> classes,
644 uint32_t sources,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800645 const PropertyMap* configuration) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800646 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, name);
Arpit Singh8e6fb252023-04-06 11:49:17 +0000647 FakeInputMapper& mapper =
648 device->addMapper<FakeInputMapper>(eventHubId,
649 mFakePolicy->getReaderConfiguration(), sources);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -0800650 mReader->pushNextDevice(device);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800651 addDevice(eventHubId, name, classes, configuration);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800652 return mapper;
653 }
654};
655
Chris Ye98d3f532020-10-01 21:48:59 -0700656TEST_F(InputReaderTest, PolicyGetInputDevices) {
657 ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard", InputDeviceClass::KEYBOARD, nullptr));
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700658 ASSERT_NO_FATAL_FAILURE(addDevice(2, "ignored", ftl::Flags<InputDeviceClass>(0),
Chris Ye98d3f532020-10-01 21:48:59 -0700659 nullptr)); // no classes so device will be ignored
Michael Wrightd02c5b62014-02-10 15:10:22 -0800660
661 // Should also have received a notification describing the new input devices.
Chris Ye98d3f532020-10-01 21:48:59 -0700662 const std::vector<InputDeviceInfo>& inputDevices = mFakePolicy->getInputDevices();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800663 ASSERT_EQ(1U, inputDevices.size());
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800664 ASSERT_EQ(END_RESERVED_ID + 1, inputDevices[0].getId());
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100665 ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800666 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, inputDevices[0].getKeyboardType());
667 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, inputDevices[0].getSources());
Siarhei Vishniakou1983a712021-06-04 19:27:09 +0000668 ASSERT_EQ(0U, inputDevices[0].getMotionRanges().size());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800669}
670
Vaibhav Devmurari5fc7d852023-03-17 18:43:33 +0000671TEST_F(InputReaderTest, InputDeviceRecreatedOnSysfsNodeChanged) {
672 ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard", InputDeviceClass::KEYBOARD, nullptr));
673 mFakeEventHub->setSysfsRootPath(1, "xyz");
674
675 // Should also have received a notification describing the new input device.
676 ASSERT_EQ(1U, mFakePolicy->getInputDevices().size());
677 InputDeviceInfo inputDevice = mFakePolicy->getInputDevices()[0];
678 ASSERT_EQ(0U, inputDevice.getLights().size());
679
680 RawLightInfo infoMonolight = {.id = 123,
681 .name = "mono_keyboard_backlight",
682 .maxBrightness = 255,
683 .flags = InputLightClass::BRIGHTNESS,
684 .path = ""};
685 mFakeEventHub->addRawLightInfo(/*rawId=*/123, std::move(infoMonolight));
686 mReader->sysfsNodeChanged("xyz");
687 mReader->loopOnce();
688
689 // Should also have received a notification describing the new recreated input device.
690 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
691 inputDevice = mFakePolicy->getInputDevices()[0];
692 ASSERT_EQ(1U, inputDevice.getLights().size());
693}
694
Chris Yee7310032020-09-22 15:36:28 -0700695TEST_F(InputReaderTest, GetMergedInputDevices) {
696 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
697 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
698 // Add two subdevices to device
699 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
700 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000701 device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
702 AINPUT_SOURCE_KEYBOARD);
703 device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
704 AINPUT_SOURCE_KEYBOARD);
Chris Yee7310032020-09-22 15:36:28 -0700705
706 // Push same device instance for next device to be added, so they'll have same identifier.
707 mReader->pushNextDevice(device);
708 mReader->pushNextDevice(device);
709 ASSERT_NO_FATAL_FAILURE(
710 addDevice(eventHubIds[0], "fake1", InputDeviceClass::KEYBOARD, nullptr));
711 ASSERT_NO_FATAL_FAILURE(
712 addDevice(eventHubIds[1], "fake2", InputDeviceClass::KEYBOARD, nullptr));
713
714 // Two devices will be merged to one input device as they have same identifier
Siarhei Vishniakou1983a712021-06-04 19:27:09 +0000715 ASSERT_EQ(1U, mFakePolicy->getInputDevices().size());
Chris Yee7310032020-09-22 15:36:28 -0700716}
717
Chris Yee14523a2020-12-19 13:46:00 -0800718TEST_F(InputReaderTest, GetMergedInputDevicesEnabled) {
719 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
720 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
721 // Add two subdevices to device
722 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
723 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000724 device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
725 AINPUT_SOURCE_KEYBOARD);
726 device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
727 AINPUT_SOURCE_KEYBOARD);
Chris Yee14523a2020-12-19 13:46:00 -0800728
729 // Push same device instance for next device to be added, so they'll have same identifier.
730 mReader->pushNextDevice(device);
731 mReader->pushNextDevice(device);
732 // Sensor device is initially disabled
733 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1",
734 InputDeviceClass::KEYBOARD | InputDeviceClass::SENSOR,
735 nullptr));
736 // Device is disabled because the only sub device is a sensor device and disabled initially.
737 ASSERT_FALSE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
738 ASSERT_FALSE(device->isEnabled());
739 ASSERT_NO_FATAL_FAILURE(
740 addDevice(eventHubIds[1], "fake2", InputDeviceClass::KEYBOARD, nullptr));
741 // The merged device is enabled if any sub device is enabled
742 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
743 ASSERT_TRUE(device->isEnabled());
744}
745
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700746TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800747 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700748 constexpr ftl::Flags<InputDeviceClass> deviceClass(InputDeviceClass::KEYBOARD);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800749 constexpr int32_t eventHubId = 1;
750 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700751 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000752 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
753 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -0800754 mReader->pushNextDevice(device);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800755 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700756
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700757 NotifyDeviceResetArgs resetArgs;
758 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700759 ASSERT_EQ(deviceId, resetArgs.deviceId);
760
761 ASSERT_EQ(device->isEnabled(), true);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800762 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000763 mReader->loopOnce();
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700764
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700765 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700766 ASSERT_EQ(deviceId, resetArgs.deviceId);
767 ASSERT_EQ(device->isEnabled(), false);
768
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800769 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000770 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700771 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700772 ASSERT_EQ(device->isEnabled(), false);
773
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800774 enableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000775 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700776 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700777 ASSERT_EQ(deviceId, resetArgs.deviceId);
778 ASSERT_EQ(device->isEnabled(), true);
779}
780
Michael Wrightd02c5b62014-02-10 15:10:22 -0800781TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800782 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700783 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800784 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800785 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800786 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800787 AINPUT_SOURCE_KEYBOARD, nullptr);
788 mapper.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800789
790 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(0,
791 AINPUT_SOURCE_ANY, AKEYCODE_A))
792 << "Should return unknown when the device id is >= 0 but unknown.";
793
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800794 ASSERT_EQ(AKEY_STATE_UNKNOWN,
795 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
796 << "Should return unknown when the device id is valid but the sources are not "
797 "supported by the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800798
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800799 ASSERT_EQ(AKEY_STATE_DOWN,
800 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
801 AKEYCODE_A))
802 << "Should return value provided by mapper when device id is valid and the device "
803 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800804
805 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(-1,
806 AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
807 << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
808
809 ASSERT_EQ(AKEY_STATE_DOWN, mReader->getKeyCodeState(-1,
810 AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
811 << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
812}
813
Philip Junker4af3b3d2021-12-14 10:36:55 +0100814TEST_F(InputReaderTest, GetKeyCodeForKeyLocation_ForwardsRequestsToMappers) {
815 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
816 constexpr int32_t eventHubId = 1;
817 FakeInputMapper& mapper = addDeviceWithFakeInputMapper(deviceId, eventHubId, "keyboard",
818 InputDeviceClass::KEYBOARD,
819 AINPUT_SOURCE_KEYBOARD, nullptr);
820 mapper.addKeyCodeMapping(AKEYCODE_Y, AKEYCODE_Z);
821
822 ASSERT_EQ(AKEYCODE_UNKNOWN, mReader->getKeyCodeForKeyLocation(0, AKEYCODE_Y))
823 << "Should return unknown when the device with the specified id is not found.";
824
825 ASSERT_EQ(AKEYCODE_Z, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_Y))
826 << "Should return correct mapping when device id is valid and mapping exists.";
827
828 ASSERT_EQ(AKEYCODE_A, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_A))
829 << "Should return the location key code when device id is valid and there's no "
830 "mapping.";
831}
832
833TEST_F(InputReaderTest, GetKeyCodeForKeyLocation_NoKeyboardMapper) {
834 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
835 constexpr int32_t eventHubId = 1;
836 FakeInputMapper& mapper = addDeviceWithFakeInputMapper(deviceId, eventHubId, "joystick",
837 InputDeviceClass::JOYSTICK,
838 AINPUT_SOURCE_GAMEPAD, nullptr);
839 mapper.addKeyCodeMapping(AKEYCODE_Y, AKEYCODE_Z);
840
841 ASSERT_EQ(AKEYCODE_UNKNOWN, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_Y))
842 << "Should return unknown when the device id is valid but there is no keyboard mapper";
843}
844
Michael Wrightd02c5b62014-02-10 15:10:22 -0800845TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800846 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700847 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800848 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800849 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800850 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800851 AINPUT_SOURCE_KEYBOARD, nullptr);
852 mapper.setScanCodeState(KEY_A, AKEY_STATE_DOWN);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800853
854 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(0,
855 AINPUT_SOURCE_ANY, KEY_A))
856 << "Should return unknown when the device id is >= 0 but unknown.";
857
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800858 ASSERT_EQ(AKEY_STATE_UNKNOWN,
859 mReader->getScanCodeState(deviceId, AINPUT_SOURCE_TRACKBALL, KEY_A))
860 << "Should return unknown when the device id is valid but the sources are not "
861 "supported by the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800862
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800863 ASSERT_EQ(AKEY_STATE_DOWN,
864 mReader->getScanCodeState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
865 KEY_A))
866 << "Should return value provided by mapper when device id is valid and the device "
867 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800868
869 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(-1,
870 AINPUT_SOURCE_TRACKBALL, KEY_A))
871 << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
872
873 ASSERT_EQ(AKEY_STATE_DOWN, mReader->getScanCodeState(-1,
874 AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, KEY_A))
875 << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
876}
877
878TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800879 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700880 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800881 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800882 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800883 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800884 AINPUT_SOURCE_KEYBOARD, nullptr);
885 mapper.setSwitchState(SW_LID, AKEY_STATE_DOWN);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800886
887 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(0,
888 AINPUT_SOURCE_ANY, SW_LID))
889 << "Should return unknown when the device id is >= 0 but unknown.";
890
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800891 ASSERT_EQ(AKEY_STATE_UNKNOWN,
892 mReader->getSwitchState(deviceId, AINPUT_SOURCE_TRACKBALL, SW_LID))
893 << "Should return unknown when the device id is valid but the sources are not "
894 "supported by the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800895
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800896 ASSERT_EQ(AKEY_STATE_DOWN,
897 mReader->getSwitchState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
898 SW_LID))
899 << "Should return value provided by mapper when device id is valid and the device "
900 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800901
902 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(-1,
903 AINPUT_SOURCE_TRACKBALL, SW_LID))
904 << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
905
906 ASSERT_EQ(AKEY_STATE_DOWN, mReader->getSwitchState(-1,
907 AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, SW_LID))
908 << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
909}
910
911TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800912 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700913 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800914 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800915 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800916 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800917 AINPUT_SOURCE_KEYBOARD, nullptr);
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100918
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800919 mapper.addSupportedKeyCode(AKEYCODE_A);
920 mapper.addSupportedKeyCode(AKEYCODE_B);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800921
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700922 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800923 uint8_t flags[4] = { 0, 0, 0, 1 };
924
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700925 ASSERT_FALSE(mReader->hasKeys(0, AINPUT_SOURCE_ANY, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800926 << "Should return false when device id is >= 0 but unknown.";
927 ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
928
929 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700930 ASSERT_FALSE(mReader->hasKeys(deviceId, AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800931 << "Should return false when device id is valid but the sources are not supported by "
932 "the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800933 ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
934
935 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700936 ASSERT_TRUE(mReader->hasKeys(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800937 keyCodes, flags))
938 << "Should return value provided by mapper when device id is valid and the device "
939 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800940 ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
941
942 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700943 ASSERT_FALSE(mReader->hasKeys(-1, AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
944 << "Should return false when the device id is < 0 but the sources are not supported by "
945 "any device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800946 ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
947
948 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700949 ASSERT_TRUE(
950 mReader->hasKeys(-1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
951 << "Should return value provided by mapper when device id is < 0 and one of the "
952 "devices supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800953 ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
954}
955
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000956TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800957 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700958 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000959 constexpr nsecs_t when = 0;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800960 constexpr int32_t eventHubId = 1;
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000961 constexpr nsecs_t readTime = 2;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800962 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800963 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800964 AINPUT_SOURCE_KEYBOARD, nullptr);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800965
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000966 mFakeEventHub->enqueueEvent(when, readTime, eventHubId, EV_KEY, KEY_A, 1);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000967 mReader->loopOnce();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800968 ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty());
969
970 RawEvent event;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800971 ASSERT_NO_FATAL_FAILURE(mapper.assertProcessWasCalled(&event));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000972 ASSERT_EQ(when, event.when);
973 ASSERT_EQ(readTime, event.readTime);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800974 ASSERT_EQ(eventHubId, event.deviceId);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800975 ASSERT_EQ(EV_KEY, event.type);
976 ASSERT_EQ(KEY_A, event.code);
977 ASSERT_EQ(1, event.value);
978}
979
Garfield Tan1c7bc862020-01-28 13:24:04 -0800980TEST_F(InputReaderTest, DeviceReset_RandomId) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800981 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700982 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800983 constexpr int32_t eventHubId = 1;
984 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
Prabir Pradhan42611e02018-11-27 14:04:02 -0800985 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000986 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
987 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -0800988 mReader->pushNextDevice(device);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800989 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Prabir Pradhan42611e02018-11-27 14:04:02 -0800990
991 NotifyDeviceResetArgs resetArgs;
992 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800993 int32_t prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -0800994
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800995 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000996 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700997 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tan1c7bc862020-01-28 13:24:04 -0800998 ASSERT_NE(prevId, resetArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800999 prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001000
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001001 enableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001002 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -07001003 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tan1c7bc862020-01-28 13:24:04 -08001004 ASSERT_NE(prevId, resetArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001005 prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001006
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001007 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001008 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -07001009 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tan1c7bc862020-01-28 13:24:04 -08001010 ASSERT_NE(prevId, resetArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001011 prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001012}
1013
Garfield Tan1c7bc862020-01-28 13:24:04 -08001014TEST_F(InputReaderTest, DeviceReset_GenerateIdWithInputReaderSource) {
1015 constexpr int32_t deviceId = 1;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001016 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Garfield Tan1c7bc862020-01-28 13:24:04 -08001017 constexpr int32_t eventHubId = 1;
1018 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
1019 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +00001020 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
1021 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001022 mReader->pushNextDevice(device);
Garfield Tan1c7bc862020-01-28 13:24:04 -08001023 ASSERT_NO_FATAL_FAILURE(addDevice(deviceId, "fake", deviceClass, nullptr));
1024
1025 NotifyDeviceResetArgs resetArgs;
1026 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1027 ASSERT_EQ(IdGenerator::Source::INPUT_READER, IdGenerator::getSource(resetArgs.id));
1028}
1029
Arthur Hungc23540e2018-11-29 20:42:11 +08001030TEST_F(InputReaderTest, Device_CanDispatchToDisplay) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001031 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001032 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001033 constexpr int32_t eventHubId = 1;
Arthur Hungc23540e2018-11-29 20:42:11 +08001034 const char* DEVICE_LOCATION = "USB1";
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001035 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
1036 FakeInputMapper& mapper =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001037 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
1038 AINPUT_SOURCE_TOUCHSCREEN);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001039 mReader->pushNextDevice(device);
Arthur Hungc23540e2018-11-29 20:42:11 +08001040
1041 const uint8_t hdmi1 = 1;
1042
1043 // Associated touch screen with second display.
1044 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
1045
1046 // Add default and second display.
Prabir Pradhan28efc192019-11-05 01:10:04 +00001047 mFakePolicy->clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00001048 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00001049 /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL);
Arthur Hungc23540e2018-11-29 20:42:11 +08001050 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +00001051 ui::ROTATION_0, /*isActive=*/true, "local:1", hdmi1,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01001052 ViewportType::EXTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001053 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::DISPLAY_INFO);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001054 mReader->loopOnce();
Prabir Pradhan28efc192019-11-05 01:10:04 +00001055
1056 // Add the device, and make sure all of the callbacks are triggered.
1057 // The device is added after the input port associations are processed since
1058 // we do not yet support dynamic device-to-display associations.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001059 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Prabir Pradhan28efc192019-11-05 01:10:04 +00001060 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001061 ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
Arthur Hungc23540e2018-11-29 20:42:11 +08001062
Arthur Hung2c9a3342019-07-23 14:18:59 +08001063 // Device should only dispatch to the specified display.
Arthur Hungc23540e2018-11-29 20:42:11 +08001064 ASSERT_EQ(deviceId, device->getId());
1065 ASSERT_FALSE(mReader->canDispatchToDisplay(deviceId, DISPLAY_ID));
1066 ASSERT_TRUE(mReader->canDispatchToDisplay(deviceId, SECONDARY_DISPLAY_ID));
Arthur Hung2c9a3342019-07-23 14:18:59 +08001067
1068 // Can't dispatch event from a disabled device.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001069 disableDevice(deviceId);
Prabir Pradhan28efc192019-11-05 01:10:04 +00001070 mReader->loopOnce();
Arthur Hung2c9a3342019-07-23 14:18:59 +08001071 ASSERT_FALSE(mReader->canDispatchToDisplay(deviceId, SECONDARY_DISPLAY_ID));
Arthur Hungc23540e2018-11-29 20:42:11 +08001072}
1073
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001074TEST_F(InputReaderTest, WhenEnabledChanges_AllSubdevicesAreUpdated) {
1075 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001076 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001077 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
1078 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
1079 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +00001080 device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
1081 AINPUT_SOURCE_KEYBOARD);
1082 device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
1083 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001084 mReader->pushNextDevice(device);
1085 mReader->pushNextDevice(device);
1086 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1", deviceClass, nullptr));
1087 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[1], "fake2", deviceClass, nullptr));
1088
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001089 NotifyDeviceResetArgs resetArgs;
1090 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1091 ASSERT_EQ(deviceId, resetArgs.deviceId);
1092 ASSERT_TRUE(device->isEnabled());
1093 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
1094 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
1095
1096 disableDevice(deviceId);
1097 mReader->loopOnce();
1098
1099 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1100 ASSERT_EQ(deviceId, resetArgs.deviceId);
1101 ASSERT_FALSE(device->isEnabled());
1102 ASSERT_FALSE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
1103 ASSERT_FALSE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
1104
1105 enableDevice(deviceId);
1106 mReader->loopOnce();
1107
1108 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1109 ASSERT_EQ(deviceId, resetArgs.deviceId);
1110 ASSERT_TRUE(device->isEnabled());
1111 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
1112 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
1113}
1114
1115TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToSubdeviceMappers) {
1116 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001117 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001118 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
1119 // Add two subdevices to device
1120 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
1121 FakeInputMapper& mapperDevice1 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001122 device->addMapper<FakeInputMapper>(eventHubIds[0],
1123 mFakePolicy->getReaderConfiguration(),
1124 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001125 FakeInputMapper& mapperDevice2 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001126 device->addMapper<FakeInputMapper>(eventHubIds[1],
1127 mFakePolicy->getReaderConfiguration(),
1128 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001129 mReader->pushNextDevice(device);
1130 mReader->pushNextDevice(device);
1131 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1", deviceClass, nullptr));
1132 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[1], "fake2", deviceClass, nullptr));
1133
1134 mapperDevice1.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
1135 mapperDevice2.setKeyCodeState(AKEYCODE_B, AKEY_STATE_DOWN);
1136
1137 ASSERT_EQ(AKEY_STATE_DOWN,
1138 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_A));
1139 ASSERT_EQ(AKEY_STATE_DOWN,
1140 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_B));
1141 ASSERT_EQ(AKEY_STATE_UNKNOWN,
1142 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_C));
1143}
1144
Prabir Pradhan7e186182020-11-10 13:56:45 -08001145TEST_F(InputReaderTest, ChangingPointerCaptureNotifiesInputListener) {
1146 NotifyPointerCaptureChangedArgs args;
1147
Hiroki Sato25040232024-02-22 17:21:22 +09001148 auto request = mFakePolicy->setPointerCapture(/*window=*/sp<BBinder>::make());
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001149 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE);
Prabir Pradhan7e186182020-11-10 13:56:45 -08001150 mReader->loopOnce();
1151 mFakeListener->assertNotifyCaptureWasCalled(&args);
Hiroki Sato25040232024-02-22 17:21:22 +09001152 ASSERT_TRUE(args.request.isEnable()) << "Pointer Capture should be enabled.";
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001153 ASSERT_EQ(args.request, request) << "Pointer Capture sequence number should match.";
Prabir Pradhan7e186182020-11-10 13:56:45 -08001154
Hiroki Sato25040232024-02-22 17:21:22 +09001155 mFakePolicy->setPointerCapture(/*window=*/nullptr);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001156 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE);
Prabir Pradhan7e186182020-11-10 13:56:45 -08001157 mReader->loopOnce();
1158 mFakeListener->assertNotifyCaptureWasCalled(&args);
Hiroki Sato25040232024-02-22 17:21:22 +09001159 ASSERT_FALSE(args.request.isEnable()) << "Pointer Capture should be disabled.";
Prabir Pradhan7e186182020-11-10 13:56:45 -08001160
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001161 // Verify that the Pointer Capture state is not updated when the configuration value
Prabir Pradhan7e186182020-11-10 13:56:45 -08001162 // does not change.
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001163 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE);
Prabir Pradhan7e186182020-11-10 13:56:45 -08001164 mReader->loopOnce();
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001165 mFakeListener->assertNotifyCaptureWasNotCalled();
Prabir Pradhan7e186182020-11-10 13:56:45 -08001166}
1167
Prabir Pradhan018faea2024-05-08 21:52:54 +00001168TEST_F(InputReaderTest, GetLastUsedInputDeviceId) {
1169 constexpr int32_t FIRST_DEVICE_ID = END_RESERVED_ID + 1000;
1170 constexpr int32_t SECOND_DEVICE_ID = FIRST_DEVICE_ID + 1;
1171 FakeInputMapper& firstMapper =
1172 addDeviceWithFakeInputMapper(FIRST_DEVICE_ID, FIRST_DEVICE_ID, "first",
1173 InputDeviceClass::KEYBOARD, AINPUT_SOURCE_KEYBOARD,
1174 /*configuration=*/nullptr);
1175 FakeInputMapper& secondMapper =
1176 addDeviceWithFakeInputMapper(SECOND_DEVICE_ID, SECOND_DEVICE_ID, "second",
1177 InputDeviceClass::TOUCH_MT, AINPUT_SOURCE_STYLUS,
1178 /*configuration=*/nullptr);
1179
1180 ASSERT_EQ(ReservedInputDeviceId::INVALID_INPUT_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1181
1182 // Start a new key gesture from the first device
1183 firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
1184 .deviceId(FIRST_DEVICE_ID)
1185 .build()});
1186 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
1187 mReader->loopOnce();
1188 ASSERT_EQ(firstMapper.getDeviceId(), mReader->getLastUsedInputDeviceId());
1189
1190 // Start a new touch gesture from the second device
1191 secondMapper.setProcessResult(
1192 {MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
1193 .deviceId(SECOND_DEVICE_ID)
1194 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER))
1195 .build()});
1196 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
1197 mReader->loopOnce();
1198 ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1199
1200 // Releasing the key is not a new gesture, so it does not update the last used device
1201 firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
1202 .deviceId(FIRST_DEVICE_ID)
1203 .build()});
1204 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
1205 mReader->loopOnce();
1206 ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1207
1208 // But pressing a new key does start a new gesture
1209 firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
1210 .deviceId(FIRST_DEVICE_ID)
1211 .build()});
1212 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
1213 mReader->loopOnce();
1214 ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1215
1216 // Moving or ending a touch gesture does not update the last used device
1217 secondMapper.setProcessResult(
1218 {MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
1219 .deviceId(SECOND_DEVICE_ID)
1220 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
1221 .build()});
1222 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
1223 mReader->loopOnce();
1224 ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1225 secondMapper.setProcessResult({MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
1226 .deviceId(SECOND_DEVICE_ID)
1227 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
1228 .build()});
1229 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
1230 mReader->loopOnce();
1231 ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1232
1233 // Starting a new hover gesture updates the last used device
1234 secondMapper.setProcessResult(
1235 {MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1236 .deviceId(SECOND_DEVICE_ID)
1237 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
1238 .build()});
1239 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
1240 mReader->loopOnce();
1241 ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1242}
1243
Chris Ye87143712020-11-10 05:05:58 +00001244class FakeVibratorInputMapper : public FakeInputMapper {
1245public:
Arpit Singh8e6fb252023-04-06 11:49:17 +00001246 FakeVibratorInputMapper(InputDeviceContext& deviceContext,
1247 const InputReaderConfiguration& readerConfig, uint32_t sources)
1248 : FakeInputMapper(deviceContext, readerConfig, sources) {}
Chris Ye87143712020-11-10 05:05:58 +00001249
1250 std::vector<int32_t> getVibratorIds() override { return getDeviceContext().getVibratorIds(); }
1251};
1252
1253TEST_F(InputReaderTest, VibratorGetVibratorIds) {
1254 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001255 ftl::Flags<InputDeviceClass> deviceClass =
1256 InputDeviceClass::KEYBOARD | InputDeviceClass::VIBRATOR;
Chris Ye87143712020-11-10 05:05:58 +00001257 constexpr int32_t eventHubId = 1;
1258 const char* DEVICE_LOCATION = "BLUETOOTH";
1259 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
1260 FakeVibratorInputMapper& mapper =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001261 device->addMapper<FakeVibratorInputMapper>(eventHubId,
1262 mFakePolicy->getReaderConfiguration(),
1263 AINPUT_SOURCE_KEYBOARD);
Chris Ye87143712020-11-10 05:05:58 +00001264 mReader->pushNextDevice(device);
1265
1266 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1267 ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
1268
1269 ASSERT_EQ(mapper.getVibratorIds().size(), 2U);
1270 ASSERT_EQ(mReader->getVibratorIds(deviceId).size(), 2U);
1271}
1272
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001273// --- FakePeripheralController ---
Kim Low03ea0352020-11-06 12:45:07 -08001274
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001275class FakePeripheralController : public PeripheralControllerInterface {
Chris Yee2b1e5c2021-03-10 22:45:12 -08001276public:
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001277 FakePeripheralController(InputDeviceContext& deviceContext) : mDeviceContext(deviceContext) {}
Chris Yee2b1e5c2021-03-10 22:45:12 -08001278
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001279 ~FakePeripheralController() override {}
Chris Yee2b1e5c2021-03-10 22:45:12 -08001280
Andy Chenf9f1a022022-08-29 20:07:10 -04001281 int32_t getEventHubId() const { return getDeviceContext().getEventHubId(); }
1282
Chris Yee2b1e5c2021-03-10 22:45:12 -08001283 void populateDeviceInfo(InputDeviceInfo* deviceInfo) override {}
1284
1285 void dump(std::string& dump) override {}
1286
1287 std::optional<int32_t> getBatteryCapacity(int32_t batteryId) override {
1288 return getDeviceContext().getBatteryCapacity(batteryId);
Kim Low03ea0352020-11-06 12:45:07 -08001289 }
1290
Chris Yee2b1e5c2021-03-10 22:45:12 -08001291 std::optional<int32_t> getBatteryStatus(int32_t batteryId) override {
1292 return getDeviceContext().getBatteryStatus(batteryId);
Kim Low03ea0352020-11-06 12:45:07 -08001293 }
Chris Ye3fdbfef2021-01-06 18:45:18 -08001294
1295 bool setLightColor(int32_t lightId, int32_t color) override {
1296 getDeviceContext().setLightBrightness(lightId, color >> 24);
1297 return true;
1298 }
1299
1300 std::optional<int32_t> getLightColor(int32_t lightId) override {
1301 std::optional<int32_t> result = getDeviceContext().getLightBrightness(lightId);
1302 if (!result.has_value()) {
1303 return std::nullopt;
1304 }
1305 return result.value() << 24;
1306 }
Chris Yee2b1e5c2021-03-10 22:45:12 -08001307
1308 bool setLightPlayerId(int32_t lightId, int32_t playerId) override { return true; }
1309
1310 std::optional<int32_t> getLightPlayerId(int32_t lightId) override { return std::nullopt; }
1311
1312private:
1313 InputDeviceContext& mDeviceContext;
1314 inline int32_t getDeviceId() { return mDeviceContext.getId(); }
1315 inline InputDeviceContext& getDeviceContext() { return mDeviceContext; }
Andy Chenf9f1a022022-08-29 20:07:10 -04001316 inline InputDeviceContext& getDeviceContext() const { return mDeviceContext; }
Chris Ye3fdbfef2021-01-06 18:45:18 -08001317};
1318
Chris Yee2b1e5c2021-03-10 22:45:12 -08001319TEST_F(InputReaderTest, BatteryGetCapacity) {
1320 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001321 ftl::Flags<InputDeviceClass> deviceClass =
1322 InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
Chris Yee2b1e5c2021-03-10 22:45:12 -08001323 constexpr int32_t eventHubId = 1;
1324 const char* DEVICE_LOCATION = "BLUETOOTH";
1325 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001326 FakePeripheralController& controller =
1327 device->addController<FakePeripheralController>(eventHubId);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001328 mReader->pushNextDevice(device);
1329
1330 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1331
Harry Cuttsa5b71292022-11-28 12:56:17 +00001332 ASSERT_EQ(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY),
1333 FakeEventHub::BATTERY_CAPACITY);
1334 ASSERT_EQ(mReader->getBatteryCapacity(deviceId), FakeEventHub::BATTERY_CAPACITY);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001335}
1336
1337TEST_F(InputReaderTest, BatteryGetStatus) {
1338 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001339 ftl::Flags<InputDeviceClass> deviceClass =
1340 InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
Chris Yee2b1e5c2021-03-10 22:45:12 -08001341 constexpr int32_t eventHubId = 1;
1342 const char* DEVICE_LOCATION = "BLUETOOTH";
1343 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001344 FakePeripheralController& controller =
1345 device->addController<FakePeripheralController>(eventHubId);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001346 mReader->pushNextDevice(device);
1347
1348 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1349
Harry Cuttsa5b71292022-11-28 12:56:17 +00001350 ASSERT_EQ(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY),
1351 FakeEventHub::BATTERY_STATUS);
1352 ASSERT_EQ(mReader->getBatteryStatus(deviceId), FakeEventHub::BATTERY_STATUS);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001353}
1354
Prabir Pradhane287ecd2022-09-07 21:18:05 +00001355TEST_F(InputReaderTest, BatteryGetDevicePath) {
1356 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
1357 ftl::Flags<InputDeviceClass> deviceClass =
1358 InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
1359 constexpr int32_t eventHubId = 1;
1360 const char* DEVICE_LOCATION = "BLUETOOTH";
1361 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
1362 device->addController<FakePeripheralController>(eventHubId);
1363 mReader->pushNextDevice(device);
1364
1365 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1366
Harry Cuttsa5b71292022-11-28 12:56:17 +00001367 ASSERT_EQ(mReader->getBatteryDevicePath(deviceId), FakeEventHub::BATTERY_DEVPATH);
Prabir Pradhane287ecd2022-09-07 21:18:05 +00001368}
1369
Chris Ye3fdbfef2021-01-06 18:45:18 -08001370TEST_F(InputReaderTest, LightGetColor) {
1371 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001372 ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::LIGHT;
Chris Ye3fdbfef2021-01-06 18:45:18 -08001373 constexpr int32_t eventHubId = 1;
1374 const char* DEVICE_LOCATION = "BLUETOOTH";
1375 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001376 FakePeripheralController& controller =
1377 device->addController<FakePeripheralController>(eventHubId);
Chris Ye3fdbfef2021-01-06 18:45:18 -08001378 mReader->pushNextDevice(device);
1379 RawLightInfo info = {.id = 1,
1380 .name = "Mono",
1381 .maxBrightness = 255,
1382 .flags = InputLightClass::BRIGHTNESS,
1383 .path = ""};
Harry Cutts33476232023-01-30 19:57:29 +00001384 mFakeEventHub->addRawLightInfo(/*rawId=*/1, std::move(info));
1385 mFakeEventHub->fakeLightBrightness(/*rawId=*/1, 0x55);
Chris Ye3fdbfef2021-01-06 18:45:18 -08001386
1387 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Chris Ye3fdbfef2021-01-06 18:45:18 -08001388
Harry Cutts33476232023-01-30 19:57:29 +00001389 ASSERT_TRUE(controller.setLightColor(/*lightId=*/1, LIGHT_BRIGHTNESS));
1390 ASSERT_EQ(controller.getLightColor(/*lightId=*/1), LIGHT_BRIGHTNESS);
1391 ASSERT_TRUE(mReader->setLightColor(deviceId, /*lightId=*/1, LIGHT_BRIGHTNESS));
1392 ASSERT_EQ(mReader->getLightColor(deviceId, /*lightId=*/1), LIGHT_BRIGHTNESS);
Chris Ye3fdbfef2021-01-06 18:45:18 -08001393}
1394
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001395// --- InputReaderIntegrationTest ---
1396
1397// These tests create and interact with the InputReader only through its interface.
1398// The InputReader is started during SetUp(), which starts its processing in its own
1399// thread. The tests use linux uinput to emulate input devices.
1400// NOTE: Interacting with the physical device while these tests are running may cause
1401// the tests to fail.
1402class InputReaderIntegrationTest : public testing::Test {
1403protected:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001404 std::unique_ptr<TestInputListener> mTestListener;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001405 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001406 std::unique_ptr<InputReaderInterface> mReader;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001407
Prabir Pradhanafb7d612024-01-08 22:45:24 +00001408 constexpr static auto EVENT_HAPPENED_TIMEOUT = 2000ms;
1409 constexpr static auto EVENT_DID_NOT_HAPPEN_TIMEOUT = 30ms;
1410
Chris Yea52ade12020-08-27 16:49:20 -07001411 void SetUp() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001412#if !defined(__ANDROID__)
1413 GTEST_SKIP();
1414#endif
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001415 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001416
Arpit Singh440bf652023-08-09 09:23:43 +00001417 setupInputReader();
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001418 }
1419
Chris Yea52ade12020-08-27 16:49:20 -07001420 void TearDown() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001421#if !defined(__ANDROID__)
1422 return;
1423#endif
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001424 ASSERT_EQ(mReader->stop(), OK);
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001425 mReader.reset();
1426 mTestListener.reset();
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001427 mFakePolicy.clear();
1428 }
Prabir Pradhanda20b172022-09-26 17:01:18 +00001429
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001430 std::optional<InputDeviceInfo> waitForDevice(const std::string& deviceName) {
1431 std::chrono::time_point start = std::chrono::steady_clock::now();
1432 while (true) {
1433 const std::vector<InputDeviceInfo> inputDevices = mFakePolicy->getInputDevices();
1434 const auto& it = std::find_if(inputDevices.begin(), inputDevices.end(),
1435 [&deviceName](const InputDeviceInfo& info) {
1436 return info.getIdentifier().name == deviceName;
1437 });
1438 if (it != inputDevices.end()) {
1439 return std::make_optional(*it);
1440 }
1441 std::this_thread::sleep_for(1ms);
1442 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
1443 if (elapsed > 5s) {
1444 return {};
1445 }
1446 }
Prabir Pradhanda20b172022-09-26 17:01:18 +00001447 }
Arpit Singh440bf652023-08-09 09:23:43 +00001448
1449 void setupInputReader() {
Prabir Pradhanafb7d612024-01-08 22:45:24 +00001450 mTestListener = std::make_unique<TestInputListener>(EVENT_HAPPENED_TIMEOUT,
1451 EVENT_DID_NOT_HAPPEN_TIMEOUT);
Arpit Singh440bf652023-08-09 09:23:43 +00001452
1453 mReader = std::make_unique<InputReader>(std::make_shared<EventHub>(), mFakePolicy,
1454 *mTestListener);
1455 ASSERT_EQ(mReader->start(), OK);
1456
1457 // Since this test is run on a real device, all the input devices connected
1458 // to the test device will show up in mReader. We wait for those input devices to
1459 // show up before beginning the tests.
Arpit Singh440bf652023-08-09 09:23:43 +00001460 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyInputDevicesChangedWasCalled());
Vaibhav Devmuraric109d812024-07-10 14:21:27 +00001461 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Arpit Singh440bf652023-08-09 09:23:43 +00001462 }
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001463};
1464
1465TEST_F(InputReaderIntegrationTest, TestInvalidDevice) {
1466 // An invalid input device that is only used for this test.
1467 class InvalidUinputDevice : public UinputDevice {
1468 public:
Harry Cutts33476232023-01-30 19:57:29 +00001469 InvalidUinputDevice() : UinputDevice("Invalid Device", /*productId=*/99) {}
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001470
1471 private:
1472 void configureDevice(int fd, uinput_user_dev* device) override {}
1473 };
1474
1475 const size_t numDevices = mFakePolicy->getInputDevices().size();
1476
1477 // UinputDevice does not set any event or key bits, so InputReader should not
1478 // consider it as a valid device.
1479 std::unique_ptr<UinputDevice> invalidDevice = createUinputDevice<InvalidUinputDevice>();
1480 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesNotChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001481 ASSERT_EQ(numDevices, mFakePolicy->getInputDevices().size());
1482
1483 invalidDevice.reset();
1484 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesNotChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001485 ASSERT_EQ(numDevices, mFakePolicy->getInputDevices().size());
1486}
1487
1488TEST_F(InputReaderIntegrationTest, AddNewDevice) {
1489 const size_t initialNumDevices = mFakePolicy->getInputDevices().size();
1490
1491 std::unique_ptr<UinputHomeKey> keyboard = createUinputDevice<UinputHomeKey>();
1492 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001493 ASSERT_EQ(initialNumDevices + 1, mFakePolicy->getInputDevices().size());
1494
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001495 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001496 ASSERT_TRUE(device.has_value());
1497 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, device->getKeyboardType());
1498 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources());
1499 ASSERT_EQ(0U, device->getMotionRanges().size());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001500
1501 keyboard.reset();
1502 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001503 ASSERT_EQ(initialNumDevices, mFakePolicy->getInputDevices().size());
1504}
1505
1506TEST_F(InputReaderIntegrationTest, SendsEventsToInputListener) {
1507 std::unique_ptr<UinputHomeKey> keyboard = createUinputDevice<UinputHomeKey>();
1508 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1509
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001510 NotifyKeyArgs keyArgs;
1511 keyboard->pressAndReleaseHomeKey();
1512 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs));
1513 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001514 ASSERT_LE(keyArgs.eventTime, keyArgs.readTime);
Liana Kazanova5b8217b2024-07-18 17:44:51 +00001515
1516 int32_t prevId = keyArgs.id;
1517 nsecs_t prevTimestamp = keyArgs.eventTime;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001518
1519 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs));
1520 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
Garfield Tan1c7bc862020-01-28 13:24:04 -08001521 ASSERT_NE(prevId, keyArgs.id);
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001522 ASSERT_LE(prevTimestamp, keyArgs.eventTime);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001523 ASSERT_LE(keyArgs.eventTime, keyArgs.readTime);
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001524}
Michael Wrightd02c5b62014-02-10 15:10:22 -08001525
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001526TEST_F(InputReaderIntegrationTest, ExternalStylusesButtons) {
1527 std::unique_ptr<UinputExternalStylus> stylus = createUinputDevice<UinputExternalStylus>();
1528 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1529
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001530 const auto device = waitForDevice(stylus->getName());
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001531 ASSERT_TRUE(device.has_value());
1532
Prabir Pradhana3621852022-10-14 18:57:23 +00001533 // An external stylus with buttons should also be recognized as a keyboard.
1534 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_STYLUS, device->getSources())
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001535 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1536 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, device->getKeyboardType());
1537
1538 const auto DOWN =
1539 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD));
1540 const auto UP = AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD));
1541
1542 stylus->pressAndReleaseKey(BTN_STYLUS);
1543 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1544 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
1545 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1546 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
1547
1548 stylus->pressAndReleaseKey(BTN_STYLUS2);
1549 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1550 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_SECONDARY))));
1551 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1552 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_SECONDARY))));
1553
1554 stylus->pressAndReleaseKey(BTN_STYLUS3);
1555 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1556 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_TERTIARY))));
1557 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1558 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_TERTIARY))));
1559}
1560
Prabir Pradhan3c28b942023-08-18 20:02:01 +00001561TEST_F(InputReaderIntegrationTest, KeyboardWithStylusButtons) {
1562 std::unique_ptr<UinputKeyboard> keyboard =
1563 createUinputDevice<UinputKeyboard>("KeyboardWithStylusButtons", /*productId=*/99,
1564 std::initializer_list<int>{KEY_Q, KEY_W, KEY_E,
1565 KEY_R, KEY_T, KEY_Y,
1566 BTN_STYLUS, BTN_STYLUS2,
1567 BTN_STYLUS3});
1568 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1569
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001570 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhan3c28b942023-08-18 20:02:01 +00001571 ASSERT_TRUE(device.has_value());
1572
1573 // An alphabetical keyboard that reports stylus buttons should not be recognized as a stylus.
1574 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources())
1575 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1576 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, device->getKeyboardType());
1577}
1578
Prabir Pradhan37a819b2023-08-22 23:20:16 +00001579TEST_F(InputReaderIntegrationTest, HidUsageKeyboardIsNotAStylus) {
1580 // Create a Uinput keyboard that simulates a keyboard that can report HID usage codes. The
1581 // hid-input driver reports HID usage codes using the value for EV_MSC MSC_SCAN event.
1582 std::unique_ptr<UinputKeyboardWithHidUsage> keyboard =
1583 createUinputDevice<UinputKeyboardWithHidUsage>(
1584 std::initializer_list<int>{KEY_VOLUMEUP, KEY_VOLUMEDOWN});
1585 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1586
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001587 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhan37a819b2023-08-22 23:20:16 +00001588 ASSERT_TRUE(device.has_value());
1589
1590 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources())
1591 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1592
1593 // If a device supports reporting HID usage codes, it shouldn't automatically support
1594 // stylus keys.
1595 const std::vector<int> keycodes{AKEYCODE_STYLUS_BUTTON_PRIMARY};
1596 uint8_t outFlags[] = {0};
1597 ASSERT_TRUE(mReader->hasKeys(device->getId(), AINPUT_SOURCE_KEYBOARD, keycodes, outFlags));
1598 ASSERT_EQ(0, outFlags[0]) << "Keyboard should not have stylus button";
1599}
1600
Siarhei Vishniakoua0d2b802020-05-13 14:00:31 -07001601/**
1602 * The Steam controller sends BTN_GEAR_DOWN and BTN_GEAR_UP for the two "paddle" buttons
1603 * on the back. In this test, we make sure that BTN_GEAR_DOWN / BTN_WHEEL and BTN_GEAR_UP
1604 * are passed to the listener.
1605 */
1606static_assert(BTN_GEAR_DOWN == BTN_WHEEL);
1607TEST_F(InputReaderIntegrationTest, SendsGearDownAndUpToInputListener) {
1608 std::unique_ptr<UinputSteamController> controller = createUinputDevice<UinputSteamController>();
1609 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1610 NotifyKeyArgs keyArgs;
1611
1612 controller->pressAndReleaseKey(BTN_GEAR_DOWN);
1613 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_DOWN
1614 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_UP
1615 ASSERT_EQ(BTN_GEAR_DOWN, keyArgs.scanCode);
1616
1617 controller->pressAndReleaseKey(BTN_GEAR_UP);
1618 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_DOWN
1619 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_UP
1620 ASSERT_EQ(BTN_GEAR_UP, keyArgs.scanCode);
1621}
1622
Prabir Pradhan484d55a2022-10-14 23:17:16 +00001623// --- TouchIntegrationTest ---
1624
Arpit Singh440bf652023-08-09 09:23:43 +00001625class BaseTouchIntegrationTest : public InputReaderIntegrationTest {
Arthur Hungaab25622020-01-16 11:22:11 +08001626protected:
Arthur Hungaab25622020-01-16 11:22:11 +08001627 const std::string UNIQUE_ID = "local:0";
1628
Chris Yea52ade12020-08-27 16:49:20 -07001629 void SetUp() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001630#if !defined(__ANDROID__)
1631 GTEST_SKIP();
1632#endif
Arthur Hungaab25622020-01-16 11:22:11 +08001633 InputReaderIntegrationTest::SetUp();
1634 // At least add an internal display.
Michael Wrighta9cf4192022-12-01 23:46:39 +00001635 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
1636 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Arthur Hungaab25622020-01-16 11:22:11 +08001637
1638 mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT));
1639 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001640 const auto info = waitForDevice(mDevice->getName());
Prabir Pradhanda20b172022-09-26 17:01:18 +00001641 ASSERT_TRUE(info);
1642 mDeviceInfo = *info;
Arthur Hungaab25622020-01-16 11:22:11 +08001643 }
1644
Linnan Li13bf76a2024-05-05 19:18:02 +08001645 void setDisplayInfoAndReconfigure(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
Michael Wrighta9cf4192022-12-01 23:46:39 +00001646 ui::Rotation orientation, const std::string& uniqueId,
Arthur Hungaab25622020-01-16 11:22:11 +08001647 std::optional<uint8_t> physicalPort,
1648 ViewportType viewportType) {
Harry Cutts33476232023-01-30 19:57:29 +00001649 mFakePolicy->addDisplayViewport(displayId, width, height, orientation, /*isActive=*/true,
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00001650 uniqueId, physicalPort, viewportType);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001651 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hungaab25622020-01-16 11:22:11 +08001652 }
1653
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001654 void assertReceivedMotion(int32_t action, const std::vector<Point>& points) {
1655 NotifyMotionArgs args;
1656 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1657 EXPECT_EQ(action, args.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07001658 ASSERT_EQ(points.size(), args.getPointerCount());
1659 for (size_t i = 0; i < args.getPointerCount(); i++) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001660 EXPECT_EQ(points[i].x, args.pointerCoords[i].getX());
1661 EXPECT_EQ(points[i].y, args.pointerCoords[i].getY());
1662 }
1663 }
1664
Arthur Hungaab25622020-01-16 11:22:11 +08001665 std::unique_ptr<UinputTouchScreen> mDevice;
Prabir Pradhanda20b172022-09-26 17:01:18 +00001666 InputDeviceInfo mDeviceInfo;
Arthur Hungaab25622020-01-16 11:22:11 +08001667};
1668
Arpit Singh440bf652023-08-09 09:23:43 +00001669enum class TouchIntegrationTestDisplays { DISPLAY_INTERNAL, DISPLAY_INPUT_PORT, DISPLAY_UNIQUE_ID };
1670
1671class TouchIntegrationTest : public BaseTouchIntegrationTest,
1672 public testing::WithParamInterface<TouchIntegrationTestDisplays> {
1673protected:
1674 static constexpr std::optional<uint8_t> DISPLAY_PORT = 0;
1675 const std::string INPUT_PORT = "uinput_touch/input0";
1676
1677 void SetUp() override {
1678#if !defined(__ANDROID__)
1679 GTEST_SKIP();
1680#endif
1681 if (GetParam() == TouchIntegrationTestDisplays::DISPLAY_INTERNAL) {
1682 BaseTouchIntegrationTest::SetUp();
1683 return;
1684 }
1685
1686 // setup policy with a input-port or UniqueId association to the display
1687 bool isInputPortAssociation =
1688 GetParam() == TouchIntegrationTestDisplays::DISPLAY_INPUT_PORT;
1689
1690 mFakePolicy = sp<FakeInputReaderPolicy>::make();
1691 if (isInputPortAssociation) {
1692 mFakePolicy->addInputPortAssociation(INPUT_PORT, DISPLAY_PORT.value());
1693 } else {
1694 mFakePolicy->addInputUniqueIdAssociation(INPUT_PORT, UNIQUE_ID);
1695 }
Arpit Singh440bf652023-08-09 09:23:43 +00001696
1697 InputReaderIntegrationTest::setupInputReader();
1698
1699 mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT),
1700 INPUT_PORT);
1701 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1702
1703 // Add a display linked to a physical port or UniqueId.
1704 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
1705 UNIQUE_ID, isInputPortAssociation ? DISPLAY_PORT : NO_PORT,
1706 ViewportType::INTERNAL);
1707 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001708 const auto info = waitForDevice(mDevice->getName());
Arpit Singh440bf652023-08-09 09:23:43 +00001709 ASSERT_TRUE(info);
1710 mDeviceInfo = *info;
1711 }
1712};
1713
1714TEST_P(TouchIntegrationTest, MultiTouchDeviceSource) {
Prabir Pradhanf9a41282022-10-25 17:15:50 +00001715 // The UinputTouchScreen is an MT device that supports MT_TOOL_TYPE and also supports stylus
1716 // buttons. It should show up as a touchscreen, stylus, and keyboard (for reporting button
1717 // presses).
1718 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD,
1719 mDeviceInfo.getSources());
1720}
1721
Arpit Singh440bf652023-08-09 09:23:43 +00001722TEST_P(TouchIntegrationTest, InputEvent_ProcessSingleTouch) {
Arthur Hungaab25622020-01-16 11:22:11 +08001723 NotifyMotionArgs args;
1724 const Point centerPoint = mDevice->getCenterPoint();
1725
1726 // ACTION_DOWN
Arthur Hung9ad18942021-06-19 02:04:46 +00001727 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001728 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001729 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001730 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1731 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1732
1733 // ACTION_MOVE
1734 mDevice->sendMove(centerPoint + Point(1, 1));
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001735 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001736 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1737 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1738
1739 // ACTION_UP
1740 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001741 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001742 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1743 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
1744}
1745
Arpit Singh440bf652023-08-09 09:23:43 +00001746TEST_P(TouchIntegrationTest, InputEvent_ProcessMultiTouch) {
Arthur Hungaab25622020-01-16 11:22:11 +08001747 NotifyMotionArgs args;
1748 const Point centerPoint = mDevice->getCenterPoint();
1749
1750 // ACTION_DOWN
Arthur Hung9ad18942021-06-19 02:04:46 +00001751 mDevice->sendSlot(FIRST_SLOT);
1752 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001753 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001754 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001755 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1756 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1757
1758 // ACTION_POINTER_DOWN (Second slot)
1759 const Point secondPoint = centerPoint + Point(100, 100);
1760 mDevice->sendSlot(SECOND_SLOT);
1761 mDevice->sendTrackingId(SECOND_TRACKING_ID);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001762 mDevice->sendDown(secondPoint);
1763 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001764 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001765 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001766
1767 // ACTION_MOVE (Second slot)
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001768 mDevice->sendMove(secondPoint + Point(1, 1));
1769 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001770 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1771 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1772
1773 // ACTION_POINTER_UP (Second slot)
arthurhungcc7f9802020-04-30 17:55:40 +08001774 mDevice->sendPointerUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001775 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001776 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001777 ASSERT_EQ(ACTION_POINTER_1_UP, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001778
1779 // ACTION_UP
1780 mDevice->sendSlot(FIRST_SLOT);
1781 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001782 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001783 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1784 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
1785}
1786
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001787/**
1788 * What happens when a pointer goes up while another pointer moves in the same frame? Are POINTER_UP
1789 * events guaranteed to contain the same data as a preceding MOVE, or can they contain different
1790 * data?
1791 * In this test, we try to send a change in coordinates in Pointer 0 in the same frame as the
1792 * liftoff of Pointer 1. We check that POINTER_UP event is generated first, and the MOVE event
1793 * for Pointer 0 only is generated after.
1794 * Suppose we are only interested in learning the movement of Pointer 0. If we only observe MOVE
1795 * events, we will not miss any information.
1796 * Even though the Pointer 1 up event contains updated Pointer 0 coordinates, there is another MOVE
1797 * event generated afterwards that contains the newest movement of pointer 0.
1798 * This is important for palm rejection. If there is a subsequent InputListener stage that detects
1799 * palms, and wants to cancel Pointer 1, then it is safe to simply drop POINTER_1_UP event without
1800 * losing information about non-palm pointers.
1801 */
Arpit Singh440bf652023-08-09 09:23:43 +00001802TEST_P(TouchIntegrationTest, MultiTouch_PointerMoveAndSecondPointerUp) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001803 NotifyMotionArgs args;
1804 const Point centerPoint = mDevice->getCenterPoint();
1805
1806 // ACTION_DOWN
1807 mDevice->sendSlot(FIRST_SLOT);
1808 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1809 mDevice->sendDown(centerPoint);
1810 mDevice->sendSync();
1811 assertReceivedMotion(AMOTION_EVENT_ACTION_DOWN, {centerPoint});
1812
1813 // ACTION_POINTER_DOWN (Second slot)
1814 const Point secondPoint = centerPoint + Point(100, 100);
1815 mDevice->sendSlot(SECOND_SLOT);
1816 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1817 mDevice->sendDown(secondPoint);
1818 mDevice->sendSync();
1819 assertReceivedMotion(ACTION_POINTER_1_DOWN, {centerPoint, secondPoint});
1820
1821 // ACTION_MOVE (First slot)
1822 mDevice->sendSlot(FIRST_SLOT);
1823 mDevice->sendMove(centerPoint + Point(5, 5));
1824 // ACTION_POINTER_UP (Second slot)
1825 mDevice->sendSlot(SECOND_SLOT);
1826 mDevice->sendPointerUp();
1827 // Send a single sync for the above 2 pointer updates
1828 mDevice->sendSync();
1829
1830 // First, we should get POINTER_UP for the second pointer
1831 assertReceivedMotion(ACTION_POINTER_1_UP,
1832 {/*first pointer */ centerPoint + Point(5, 5),
1833 /*second pointer*/ secondPoint});
1834
1835 // Next, the MOVE event for the first pointer
1836 assertReceivedMotion(AMOTION_EVENT_ACTION_MOVE, {centerPoint + Point(5, 5)});
1837}
1838
1839/**
1840 * Similar scenario as above. The difference is that when the second pointer goes up, it will first
1841 * move, and then it will go up, all in the same frame.
1842 * In this scenario, the movement of the second pointer just prior to liftoff is ignored, and never
1843 * gets sent to the listener.
1844 */
Arpit Singh440bf652023-08-09 09:23:43 +00001845TEST_P(TouchIntegrationTest, MultiTouch_PointerMoveAndSecondPointerMoveAndUp) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001846 NotifyMotionArgs args;
1847 const Point centerPoint = mDevice->getCenterPoint();
1848
1849 // ACTION_DOWN
1850 mDevice->sendSlot(FIRST_SLOT);
1851 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1852 mDevice->sendDown(centerPoint);
1853 mDevice->sendSync();
1854 assertReceivedMotion(AMOTION_EVENT_ACTION_DOWN, {centerPoint});
1855
1856 // ACTION_POINTER_DOWN (Second slot)
1857 const Point secondPoint = centerPoint + Point(100, 100);
1858 mDevice->sendSlot(SECOND_SLOT);
1859 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1860 mDevice->sendDown(secondPoint);
1861 mDevice->sendSync();
1862 assertReceivedMotion(ACTION_POINTER_1_DOWN, {centerPoint, secondPoint});
1863
1864 // ACTION_MOVE (First slot)
1865 mDevice->sendSlot(FIRST_SLOT);
1866 mDevice->sendMove(centerPoint + Point(5, 5));
1867 // ACTION_POINTER_UP (Second slot)
1868 mDevice->sendSlot(SECOND_SLOT);
1869 mDevice->sendMove(secondPoint + Point(6, 6));
1870 mDevice->sendPointerUp();
1871 // Send a single sync for the above 2 pointer updates
1872 mDevice->sendSync();
1873
1874 // First, we should get POINTER_UP for the second pointer
1875 // The movement of the second pointer during the liftoff frame is ignored.
1876 // The coordinates 'secondPoint + Point(6, 6)' are never sent to the listener.
1877 assertReceivedMotion(ACTION_POINTER_1_UP,
1878 {/*first pointer */ centerPoint + Point(5, 5),
1879 /*second pointer*/ secondPoint});
1880
1881 // Next, the MOVE event for the first pointer
1882 assertReceivedMotion(AMOTION_EVENT_ACTION_MOVE, {centerPoint + Point(5, 5)});
1883}
1884
Arpit Singh440bf652023-08-09 09:23:43 +00001885TEST_P(TouchIntegrationTest, InputEvent_ProcessPalm) {
Arthur Hungaab25622020-01-16 11:22:11 +08001886 NotifyMotionArgs args;
1887 const Point centerPoint = mDevice->getCenterPoint();
1888
1889 // ACTION_DOWN
arthurhungcc7f9802020-04-30 17:55:40 +08001890 mDevice->sendSlot(FIRST_SLOT);
1891 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001892 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001893 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001894 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1895 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1896
arthurhungcc7f9802020-04-30 17:55:40 +08001897 // ACTION_POINTER_DOWN (second slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001898 const Point secondPoint = centerPoint + Point(100, 100);
1899 mDevice->sendSlot(SECOND_SLOT);
1900 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1901 mDevice->sendDown(secondPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001902 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001903 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001904 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001905
arthurhungcc7f9802020-04-30 17:55:40 +08001906 // ACTION_MOVE (second slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001907 mDevice->sendMove(secondPoint + Point(1, 1));
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001908 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001909 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1910 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1911
arthurhungcc7f9802020-04-30 17:55:40 +08001912 // Send MT_TOOL_PALM (second slot), which indicates that the touch IC has determined this to be
1913 // a palm event.
1914 // Expect to receive the ACTION_POINTER_UP with cancel flag.
Arthur Hungaab25622020-01-16 11:22:11 +08001915 mDevice->sendToolType(MT_TOOL_PALM);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001916 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001917 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001918 ASSERT_EQ(ACTION_POINTER_1_UP, args.action);
arthurhungcc7f9802020-04-30 17:55:40 +08001919 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, args.flags);
Arthur Hungaab25622020-01-16 11:22:11 +08001920
arthurhungcc7f9802020-04-30 17:55:40 +08001921 // Send up to second slot, expect first slot send moving.
1922 mDevice->sendPointerUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001923 mDevice->sendSync();
arthurhungcc7f9802020-04-30 17:55:40 +08001924 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1925 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001926
arthurhungcc7f9802020-04-30 17:55:40 +08001927 // Send ACTION_UP (first slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001928 mDevice->sendSlot(FIRST_SLOT);
1929 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001930 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001931
arthurhungcc7f9802020-04-30 17:55:40 +08001932 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1933 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001934}
1935
Prabir Pradhanc09ec6d2023-08-14 22:31:43 +00001936/**
1937 * Some drivers historically have reported axis values outside of the range specified in the
1938 * evdev axis info. Ensure we don't crash when this happens. For example, a driver may report a
1939 * pressure value greater than the reported maximum, since it unclear what specific meaning the
1940 * maximum value for pressure has (beyond the maximum value that can be produced by a sensor),
1941 * and no units for pressure (resolution) is specified by the evdev documentation.
1942 */
1943TEST_P(TouchIntegrationTest, AcceptsAxisValuesOutsideReportedRange) {
1944 const Point centerPoint = mDevice->getCenterPoint();
1945
1946 // Down with pressure outside the reported range
1947 mDevice->sendSlot(FIRST_SLOT);
1948 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1949 mDevice->sendDown(centerPoint);
1950 mDevice->sendPressure(UinputTouchScreen::RAW_PRESSURE_MAX + 2);
1951 mDevice->sendSync();
1952 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1953 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
1954
1955 // Move to a point outside the reported range
1956 mDevice->sendMove(Point(DISPLAY_WIDTH, DISPLAY_HEIGHT) + Point(1, 1));
1957 mDevice->sendSync();
1958 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1959 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
1960
1961 // Up
1962 mDevice->sendUp();
1963 mDevice->sendSync();
1964 ASSERT_NO_FATAL_FAILURE(
1965 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
1966}
1967
Arpit Singh440bf652023-08-09 09:23:43 +00001968TEST_P(TouchIntegrationTest, NotifiesPolicyWhenStylusGestureStarted) {
Prabir Pradhanda20b172022-09-26 17:01:18 +00001969 const Point centerPoint = mDevice->getCenterPoint();
1970
1971 // Send down with the pen tool selected. The policy should be notified of the stylus presence.
1972 mDevice->sendSlot(FIRST_SLOT);
1973 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1974 mDevice->sendToolType(MT_TOOL_PEN);
1975 mDevice->sendDown(centerPoint);
1976 mDevice->sendSync();
1977 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1978 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001979 WithToolType(ToolType::STYLUS))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00001980
1981 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotified(mDeviceInfo.getId()));
1982
1983 // Release the stylus touch.
1984 mDevice->sendUp();
1985 mDevice->sendSync();
1986 ASSERT_NO_FATAL_FAILURE(
1987 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
1988
1989 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotNotified());
1990
1991 // Touch down with the finger, without the pen tool selected. The policy is not notified.
1992 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1993 mDevice->sendToolType(MT_TOOL_FINGER);
1994 mDevice->sendDown(centerPoint);
1995 mDevice->sendSync();
1996 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1997 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001998 WithToolType(ToolType::FINGER))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00001999
2000 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotNotified());
2001
2002 mDevice->sendUp();
2003 mDevice->sendSync();
2004 ASSERT_NO_FATAL_FAILURE(
2005 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2006
2007 // Send a move event with the stylus tool without BTN_TOUCH to generate a hover enter.
2008 // The policy should be notified of the stylus presence.
2009 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2010 mDevice->sendToolType(MT_TOOL_PEN);
2011 mDevice->sendMove(centerPoint);
2012 mDevice->sendSync();
2013 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2014 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002015 WithToolType(ToolType::STYLUS))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00002016
2017 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotified(mDeviceInfo.getId()));
2018}
2019
Arpit Singh440bf652023-08-09 09:23:43 +00002020TEST_P(TouchIntegrationTest, ExternalStylusConnectedDuringTouchGesture) {
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002021 const Point centerPoint = mDevice->getCenterPoint();
2022
2023 // Down
2024 mDevice->sendSlot(FIRST_SLOT);
2025 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2026 mDevice->sendDown(centerPoint);
2027 mDevice->sendSync();
2028 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2029 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
2030
2031 // Move
2032 mDevice->sendMove(centerPoint + Point(1, 1));
2033 mDevice->sendSync();
2034 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2035 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
2036
2037 // Connecting an external stylus mid-gesture should not interrupt the ongoing gesture stream.
2038 auto externalStylus = createUinputDevice<UinputExternalStylus>();
2039 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002040 const auto stylusInfo = waitForDevice(externalStylus->getName());
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002041 ASSERT_TRUE(stylusInfo);
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002042
2043 // Move
2044 mDevice->sendMove(centerPoint + Point(2, 2));
2045 mDevice->sendSync();
2046 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2047 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
2048
2049 // Disconnecting an external stylus mid-gesture should not interrupt the ongoing gesture stream.
2050 externalStylus.reset();
2051 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002052 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2053
2054 // Up
2055 mDevice->sendUp();
2056 mDevice->sendSync();
2057 ASSERT_NO_FATAL_FAILURE(
2058 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2059
2060 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2061}
2062
Arpit Singh440bf652023-08-09 09:23:43 +00002063INSTANTIATE_TEST_SUITE_P(TouchIntegrationTestDisplayVariants, TouchIntegrationTest,
2064 testing::Values(TouchIntegrationTestDisplays::DISPLAY_INTERNAL,
2065 TouchIntegrationTestDisplays::DISPLAY_INPUT_PORT,
2066 TouchIntegrationTestDisplays::DISPLAY_UNIQUE_ID));
2067
Prabir Pradhan124ea442022-10-28 20:27:44 +00002068// --- StylusButtonIntegrationTest ---
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002069
Prabir Pradhan124ea442022-10-28 20:27:44 +00002070// Verify the behavior of button presses reported by various kinds of styluses, including buttons
2071// reported by the touchscreen's device, by a fused external stylus, and by an un-fused external
2072// stylus.
2073template <typename UinputStylusDevice>
Arpit Singh440bf652023-08-09 09:23:43 +00002074class StylusButtonIntegrationTest : public BaseTouchIntegrationTest {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002075protected:
2076 void SetUp() override {
2077#if !defined(__ANDROID__)
2078 GTEST_SKIP();
2079#endif
Arpit Singh440bf652023-08-09 09:23:43 +00002080 BaseTouchIntegrationTest::SetUp();
Prabir Pradhan124ea442022-10-28 20:27:44 +00002081 mTouchscreen = mDevice.get();
2082 mTouchscreenInfo = mDeviceInfo;
2083
2084 setUpStylusDevice();
2085 }
2086
2087 UinputStylusDevice* mStylus{nullptr};
2088 InputDeviceInfo mStylusInfo{};
2089
2090 UinputTouchScreen* mTouchscreen{nullptr};
2091 InputDeviceInfo mTouchscreenInfo{};
2092
2093private:
2094 // When we are attempting to test stylus button events that are sent from the touchscreen,
2095 // use the same Uinput device for the touchscreen and the stylus.
2096 template <typename T = UinputStylusDevice>
2097 std::enable_if_t<std::is_same_v<UinputTouchScreen, T>, void> setUpStylusDevice() {
2098 mStylus = mDevice.get();
2099 mStylusInfo = mDeviceInfo;
2100 }
2101
2102 // When we are attempting to stylus buttons from an external stylus being merged with touches
2103 // from a touchscreen, create a new Uinput device through which stylus buttons can be injected.
2104 template <typename T = UinputStylusDevice>
2105 std::enable_if_t<!std::is_same_v<UinputTouchScreen, T>, void> setUpStylusDevice() {
2106 mStylusDeviceLifecycleTracker = createUinputDevice<T>();
2107 mStylus = mStylusDeviceLifecycleTracker.get();
2108 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002109 const auto info = waitForDevice(mStylus->getName());
Prabir Pradhan124ea442022-10-28 20:27:44 +00002110 ASSERT_TRUE(info);
2111 mStylusInfo = *info;
2112 }
2113
2114 std::unique_ptr<UinputStylusDevice> mStylusDeviceLifecycleTracker{};
2115
2116 // Hide the base class's device to expose it with a different name for readability.
Arpit Singh440bf652023-08-09 09:23:43 +00002117 using BaseTouchIntegrationTest::mDevice;
2118 using BaseTouchIntegrationTest::mDeviceInfo;
Prabir Pradhan124ea442022-10-28 20:27:44 +00002119};
2120
2121using StylusButtonIntegrationTestTypes =
2122 ::testing::Types<UinputTouchScreen, UinputExternalStylus, UinputExternalStylusWithPressure>;
2123TYPED_TEST_SUITE(StylusButtonIntegrationTest, StylusButtonIntegrationTestTypes);
2124
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002125TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsGenerateKeyEvents) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002126 const auto stylusId = TestFixture::mStylusInfo.getId();
2127
2128 TestFixture::mStylus->pressKey(BTN_STYLUS);
2129 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2130 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2131 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2132
2133 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2134 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002135 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002136 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002137}
2138
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002139TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingTouchGesture) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002140 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2141 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2142 const auto stylusId = TestFixture::mStylusInfo.getId();
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002143
2144 // Press the stylus button.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002145 TestFixture::mStylus->pressKey(BTN_STYLUS);
2146 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002147 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002148 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002149
2150 // Start and finish a stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002151 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2152 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2153 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2154 TestFixture::mTouchscreen->sendDown(centerPoint);
2155 TestFixture::mTouchscreen->sendSync();
2156 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002157 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002158 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002159 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2160 WithDeviceId(touchscreenId))));
2161 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002162 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002163 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002164 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2165 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002166
Prabir Pradhan124ea442022-10-28 20:27:44 +00002167 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2168 TestFixture::mTouchscreen->sendSync();
2169 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002170 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002171 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002172 WithDeviceId(touchscreenId))));
2173 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002174 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002175 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002176 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002177
2178 // Release the stylus button.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002179 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2180 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002181 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002182 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002183}
2184
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002185TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingHoveringTouchGesture) {
Prabir Pradhan9a561c22022-11-07 16:11:23 +00002186 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2187 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2188 const auto stylusId = TestFixture::mStylusInfo.getId();
2189 auto toolTypeDevice =
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002190 AllOf(WithToolType(ToolType::STYLUS), WithDeviceId(touchscreenId));
Prabir Pradhan9a561c22022-11-07 16:11:23 +00002191
2192 // Press the stylus button.
2193 TestFixture::mStylus->pressKey(BTN_STYLUS);
2194 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2195 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2196 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2197
2198 // Start hovering with the stylus.
2199 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2200 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2201 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2202 TestFixture::mTouchscreen->sendMove(centerPoint);
2203 TestFixture::mTouchscreen->sendSync();
2204 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2205 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2206 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2207 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2208 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2209 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2210 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2211 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
2212 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2213
2214 // Touch down with the stylus.
2215 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2216 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2217 TestFixture::mTouchscreen->sendDown(centerPoint);
2218 TestFixture::mTouchscreen->sendSync();
2219 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2220 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
2221 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2222
2223 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2224 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
2225 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2226
2227 // Stop touching with the stylus, and start hovering.
2228 TestFixture::mTouchscreen->sendUp();
2229 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2230 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2231 TestFixture::mTouchscreen->sendMove(centerPoint);
2232 TestFixture::mTouchscreen->sendSync();
2233 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2234 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_UP),
2235 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2236 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2237 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2238 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2239 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2240 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2241 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2242
2243 // Stop hovering.
2244 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2245 TestFixture::mTouchscreen->sendSync();
2246 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2247 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
2248 WithButtonState(0))));
2249 // TODO(b/257971675): Fix inconsistent button state when exiting hover.
2250 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2251 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
2252 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2253
2254 // Release the stylus button.
2255 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2256 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2257 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
2258 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2259}
2260
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002261TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsWithinTouchGesture) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002262 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2263 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2264 const auto stylusId = TestFixture::mStylusInfo.getId();
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002265
2266 // Start a stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002267 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2268 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2269 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2270 TestFixture::mTouchscreen->sendDown(centerPoint);
2271 TestFixture::mTouchscreen->sendSync();
2272 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002273 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002274 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002275 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002276
2277 // Press and release a stylus button. Each change in button state also generates a MOVE event.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002278 TestFixture::mStylus->pressKey(BTN_STYLUS);
2279 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002280 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002281 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2282 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002283 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002284 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002285 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2286 WithDeviceId(touchscreenId))));
2287 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002288 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002289 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002290 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2291 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002292
Prabir Pradhan124ea442022-10-28 20:27:44 +00002293 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2294 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002295 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002296 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2297 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002298 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002299 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002300 WithDeviceId(touchscreenId))));
2301 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002302 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002303 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002304 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002305
2306 // Finish the stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002307 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2308 TestFixture::mTouchscreen->sendSync();
2309 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002310 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002311 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002312 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002313}
2314
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002315TYPED_TEST(StylusButtonIntegrationTest, StylusButtonMotionEventsDisabled) {
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002316 TestFixture::mFakePolicy->setStylusButtonMotionEventsEnabled(false);
2317 TestFixture::mReader->requestRefreshConfiguration(
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002318 InputReaderConfiguration::Change::STYLUS_BUTTON_REPORTING);
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002319
2320 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2321 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2322 const auto stylusId = TestFixture::mStylusInfo.getId();
2323
2324 // Start a stylus gesture. By the time this event is processed, the configuration change that
2325 // was requested is guaranteed to be completed.
2326 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2327 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2328 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2329 TestFixture::mTouchscreen->sendDown(centerPoint);
2330 TestFixture::mTouchscreen->sendSync();
2331 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2332 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002333 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002334 WithDeviceId(touchscreenId))));
2335
2336 // Press and release a stylus button. Each change only generates a MOVE motion event.
2337 // Key events are unaffected.
2338 TestFixture::mStylus->pressKey(BTN_STYLUS);
2339 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2340 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2341 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2342 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2343 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002344 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002345 WithDeviceId(touchscreenId))));
2346
2347 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2348 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2349 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
2350 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2351 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2352 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002353 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002354 WithDeviceId(touchscreenId))));
2355
2356 // Finish the stylus gesture.
2357 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2358 TestFixture::mTouchscreen->sendSync();
2359 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2360 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002361 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002362 WithDeviceId(touchscreenId))));
2363}
2364
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002365// --- ExternalStylusIntegrationTest ---
2366
2367// Verify the behavior of an external stylus. An external stylus can report pressure or button
2368// data independently of the touchscreen, which is then sent as a MotionEvent as part of an
2369// ongoing stylus gesture that is being emitted by the touchscreen.
Arpit Singh440bf652023-08-09 09:23:43 +00002370using ExternalStylusIntegrationTest = BaseTouchIntegrationTest;
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002371
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002372TEST_F(ExternalStylusIntegrationTest, ExternalStylusConnectionChangesTouchscreenSource) {
2373 // Create an external stylus capable of reporting pressure data that
2374 // should be fused with a touch pointer.
2375 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2376 createUinputDevice<UinputExternalStylusWithPressure>();
2377 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002378 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002379 ASSERT_TRUE(stylusInfo);
2380
2381 // Connecting an external stylus changes the source of the touchscreen.
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002382 const auto deviceInfo = waitForDevice(mDevice->getName());
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002383 ASSERT_TRUE(deviceInfo);
2384 ASSERT_TRUE(isFromSource(deviceInfo->getSources(), STYLUS_FUSION_SOURCE));
2385}
2386
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002387TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureReported) {
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002388 const Point centerPoint = mDevice->getCenterPoint();
2389
2390 // Create an external stylus capable of reporting pressure data that
2391 // should be fused with a touch pointer.
2392 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2393 createUinputDevice<UinputExternalStylusWithPressure>();
2394 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002395 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002396 ASSERT_TRUE(stylusInfo);
2397
2398 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2399
2400 const auto touchscreenId = mDeviceInfo.getId();
2401
2402 // Set a pressure value on the stylus. It doesn't generate any events.
2403 const auto& RAW_PRESSURE_MAX = UinputExternalStylusWithPressure::RAW_PRESSURE_MAX;
2404 stylus->setPressure(100);
2405 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2406
2407 // Start a finger gesture, and ensure it shows up as stylus gesture
2408 // with the pressure set by the external stylus.
Dominik Laskowski2f01d772022-03-23 16:01:29 -07002409 mDevice->sendSlot(FIRST_SLOT);
Chris Ye1b0c7342020-07-28 21:57:03 -07002410 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002411 mDevice->sendToolType(MT_TOOL_FINGER);
Prabir Pradhanb54ffb22022-10-27 18:03:34 +00002412 mDevice->sendDown(centerPoint);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002413 mDevice->sendSync();
2414 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002415 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithToolType(ToolType::STYLUS),
2416 WithButtonState(0), WithSource(STYLUS_FUSION_SOURCE), WithDeviceId(touchscreenId),
2417 WithPressure(100.f / RAW_PRESSURE_MAX))));
Dominik Laskowski2f01d772022-03-23 16:01:29 -07002418
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002419 // Change the pressure on the external stylus, and ensure the touchscreen generates a MOVE
2420 // event with the updated pressure.
2421 stylus->setPressure(200);
Vaibhav Devmuraridd82b8e2022-08-16 15:34:01 +00002422 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002423 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithToolType(ToolType::STYLUS),
2424 WithButtonState(0), WithSource(STYLUS_FUSION_SOURCE), WithDeviceId(touchscreenId),
2425 WithPressure(200.f / RAW_PRESSURE_MAX))));
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002426
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002427 // The external stylus did not generate any events.
2428 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2429 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
2430}
2431
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002432TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureNotReported) {
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002433 const Point centerPoint = mDevice->getCenterPoint();
2434
2435 // Create an external stylus capable of reporting pressure data that
2436 // should be fused with a touch pointer.
2437 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2438 createUinputDevice<UinputExternalStylusWithPressure>();
2439 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002440 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002441 ASSERT_TRUE(stylusInfo);
2442
2443 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2444
2445 const auto touchscreenId = mDeviceInfo.getId();
2446
2447 // Set a pressure value of 0 on the stylus. It doesn't generate any events.
2448 const auto& RAW_PRESSURE_MAX = UinputExternalStylusWithPressure::RAW_PRESSURE_MAX;
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002449 // Send a non-zero value first to prevent the kernel from consuming the zero event.
2450 stylus->setPressure(100);
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002451 stylus->setPressure(0);
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002452 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002453
2454 // Start a finger gesture. The touch device will withhold generating any touches for
2455 // up to 72 milliseconds while waiting for pressure data from the external stylus.
2456 mDevice->sendSlot(FIRST_SLOT);
2457 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2458 mDevice->sendToolType(MT_TOOL_FINGER);
2459 mDevice->sendDown(centerPoint);
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002460 const auto syncTime = std::chrono::system_clock::now();
2461 // After 72 ms, the event *will* be generated. If we wait the full 72 ms to check that NO event
2462 // is generated in that period, there will be a race condition between the event being generated
2463 // and the test's wait timeout expiring. Thus, we wait for a shorter duration in the test, which
2464 // will reduce the liklihood of the race condition occurring.
2465 const auto waitUntilTimeForNoEvent =
2466 syncTime + std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT / 2));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07002467 mDevice->sendSync();
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002468 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled(waitUntilTimeForNoEvent));
Michael Wrightd02c5b62014-02-10 15:10:22 -08002469
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002470 // Since the external stylus did not report a pressure value within the timeout,
2471 // it shows up as a finger pointer.
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002472 const auto waitUntilTimeForEvent = syncTime +
2473 std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT)) + EVENT_HAPPENED_TIMEOUT;
2474 ASSERT_NO_FATAL_FAILURE(
2475 mTestListener->assertNotifyMotionWasCalled(AllOf(WithMotionAction(
2476 AMOTION_EVENT_ACTION_DOWN),
2477 WithSource(AINPUT_SOURCE_TOUCHSCREEN |
2478 AINPUT_SOURCE_STYLUS),
2479 WithToolType(ToolType::FINGER),
2480 WithDeviceId(touchscreenId),
2481 WithPressure(1.f)),
2482 waitUntilTimeForEvent));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002483
2484 // Change the pressure on the external stylus. Since the pressure was not present at the start
2485 // of the gesture, it is ignored for now.
2486 stylus->setPressure(200);
2487 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2488
2489 // Finish the finger gesture.
Michael Wrightd02c5b62014-02-10 15:10:22 -08002490 mDevice->sendTrackingId(INVALID_TRACKING_ID);
2491 mDevice->sendSync();
2492 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2493 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002494 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002495 WithToolType(ToolType::FINGER))));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002496
2497 // Start a new gesture. Since we have a valid pressure value, it shows up as a stylus.
2498 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2499 mDevice->sendToolType(MT_TOOL_FINGER);
2500 mDevice->sendDown(centerPoint);
2501 mDevice->sendSync();
2502 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002503 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithSource(STYLUS_FUSION_SOURCE),
2504 WithToolType(ToolType::STYLUS), WithButtonState(0), WithDeviceId(touchscreenId),
2505 WithPressure(200.f / RAW_PRESSURE_MAX))));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002506
2507 // The external stylus did not generate any events.
2508 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2509 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002510}
Siarhei Vishniakou1983a712021-06-04 19:27:09 +00002511
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002512TEST_F(ExternalStylusIntegrationTest, UnfusedExternalStylus) {
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002513 const Point centerPoint = mDevice->getCenterPoint();
2514
2515 // Create an external stylus device that does not support pressure. It should not affect any
2516 // touch pointers.
2517 std::unique_ptr<UinputExternalStylus> stylus = createUinputDevice<UinputExternalStylus>();
2518 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002519 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002520 ASSERT_TRUE(stylusInfo);
2521
2522 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2523
2524 const auto touchscreenId = mDeviceInfo.getId();
2525
2526 // Start a finger gesture and ensure a finger pointer is generated for it, without waiting for
2527 // pressure data from the external stylus.
2528 mDevice->sendSlot(FIRST_SLOT);
2529 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2530 mDevice->sendToolType(MT_TOOL_FINGER);
2531 mDevice->sendDown(centerPoint);
2532 auto waitUntil = std::chrono::system_clock::now() +
2533 std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT));
2534 mDevice->sendSync();
2535 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002536 mTestListener->assertNotifyMotionWasCalled(AllOf(WithMotionAction(
2537 AMOTION_EVENT_ACTION_DOWN),
2538 WithToolType(ToolType::FINGER),
2539 WithSource(AINPUT_SOURCE_TOUCHSCREEN |
2540 AINPUT_SOURCE_STYLUS),
2541 WithButtonState(0),
2542 WithDeviceId(touchscreenId),
2543 WithPressure(1.f)),
2544 waitUntil));
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002545
2546 // The external stylus did not generate any events.
2547 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2548 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
2549}
2550
Michael Wrightd02c5b62014-02-10 15:10:22 -08002551// --- InputDeviceTest ---
2552class InputDeviceTest : public testing::Test {
2553protected:
2554 static const char* DEVICE_NAME;
2555 static const char* DEVICE_LOCATION;
2556 static const int32_t DEVICE_ID;
2557 static const int32_t DEVICE_GENERATION;
2558 static const int32_t DEVICE_CONTROLLER_NUMBER;
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002559 static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002560 static const int32_t EVENTHUB_ID;
2561 static const std::string DEVICE_BLUETOOTH_ADDRESS;
2562
2563 std::shared_ptr<FakeEventHub> mFakeEventHub;
2564 sp<FakeInputReaderPolicy> mFakePolicy;
2565 std::unique_ptr<TestInputListener> mFakeListener;
2566 std::unique_ptr<InstrumentedInputReader> mReader;
2567 std::shared_ptr<InputDevice> mDevice;
2568
2569 void SetUp() override {
2570 mFakeEventHub = std::make_unique<FakeEventHub>();
2571 mFakePolicy = sp<FakeInputReaderPolicy>::make();
2572 mFakeListener = std::make_unique<TestInputListener>();
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002573 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Michael Wrightd02c5b62014-02-10 15:10:22 -08002574 *mFakeListener);
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002575 InputDeviceIdentifier identifier;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002576 identifier.name = DEVICE_NAME;
2577 identifier.location = DEVICE_LOCATION;
2578 identifier.bluetoothAddress = DEVICE_BLUETOOTH_ADDRESS;
2579 mDevice = std::make_shared<InputDevice>(mReader->getContext(), DEVICE_ID, DEVICE_GENERATION,
2580 identifier);
2581 mReader->pushNextDevice(mDevice);
2582 mFakeEventHub->addDevice(EVENTHUB_ID, DEVICE_NAME, ftl::Flags<InputDeviceClass>(0));
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002583 mReader->loopOnce();
Michael Wrightd02c5b62014-02-10 15:10:22 -08002584 }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002585
2586 void TearDown() override {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002587 mFakeListener.reset();
2588 mFakePolicy.clear();
2589 }
2590};
2591
2592const char* InputDeviceTest::DEVICE_NAME = "device";
2593const char* InputDeviceTest::DEVICE_LOCATION = "USB1";
2594const int32_t InputDeviceTest::DEVICE_ID = END_RESERVED_ID + 1000;
2595const int32_t InputDeviceTest::DEVICE_GENERATION = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002596const int32_t InputDeviceTest::DEVICE_CONTROLLER_NUMBER = 0;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002597const ftl::Flags<InputDeviceClass> InputDeviceTest::DEVICE_CLASSES =
2598 InputDeviceClass::KEYBOARD | InputDeviceClass::TOUCH | InputDeviceClass::JOYSTICK;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002599const int32_t InputDeviceTest::EVENTHUB_ID = 1;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002600const std::string InputDeviceTest::DEVICE_BLUETOOTH_ADDRESS = "11:AA:22:BB:33:CC";
2601
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002602TEST_F(InputDeviceTest, ImmutableProperties) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002603 ASSERT_EQ(DEVICE_ID, mDevice->getId());
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002604 ASSERT_STREQ(DEVICE_NAME, mDevice->getName().c_str());
2605 ASSERT_EQ(ftl::Flags<InputDeviceClass>(0), mDevice->getClasses());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002606}
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002607
Michael Wrightd02c5b62014-02-10 15:10:22 -08002608TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsFalse) {
2609 ASSERT_EQ(mDevice->isEnabled(), false);
2610}
2611
2612TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
2613 // Configuration.
2614 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002615 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002616
2617 // Reset.
2618 unused += mDevice->reset(ARBITRARY_TIME);
2619
2620 NotifyDeviceResetArgs resetArgs;
2621 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
2622 ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
2623 ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
2624
2625 // Metadata.
2626 ASSERT_TRUE(mDevice->isIgnored());
2627 ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mDevice->getSources());
2628
2629 InputDeviceInfo info = mDevice->getDeviceInfo();
2630 ASSERT_EQ(DEVICE_ID, info.getId());
2631 ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.c_str());
2632 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NONE, info.getKeyboardType());
2633 ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, info.getSources());
2634
2635 // State queries.
2636 ASSERT_EQ(0, mDevice->getMetaState());
2637
2638 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, 0))
2639 << "Ignored device should return unknown key code state.";
2640 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 0))
2641 << "Ignored device should return unknown scan code state.";
2642 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 0))
2643 << "Ignored device should return unknown switch state.";
2644
2645 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B};
2646 uint8_t flags[2] = { 0, 1 };
2647 ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, keyCodes, flags))
2648 << "Ignored device should never mark any key codes.";
2649 ASSERT_EQ(0, flags[0]) << "Flag for unsupported key should be unchanged.";
2650 ASSERT_EQ(1, flags[1]) << "Flag for unsupported key should be unchanged.";
2651}
2652
2653TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRequestsToMappers) {
2654 // Configuration.
2655 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "key", "value");
2656
2657 FakeInputMapper& mapper1 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00002658 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2659 AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002660 mapper1.setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC);
2661 mapper1.setMetaState(AMETA_ALT_ON);
2662 mapper1.addSupportedKeyCode(AKEYCODE_A);
2663 mapper1.addSupportedKeyCode(AKEYCODE_B);
2664 mapper1.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
2665 mapper1.setKeyCodeState(AKEYCODE_B, AKEY_STATE_UP);
2666 mapper1.setScanCodeState(2, AKEY_STATE_DOWN);
2667 mapper1.setScanCodeState(3, AKEY_STATE_UP);
2668 mapper1.setSwitchState(4, AKEY_STATE_DOWN);
2669
2670 FakeInputMapper& mapper2 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00002671 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2672 AINPUT_SOURCE_TOUCHSCREEN);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002673 mapper2.setMetaState(AMETA_SHIFT_ON);
2674
2675 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002676 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002677
Harry Cuttsf13161a2023-03-08 14:15:49 +00002678 std::optional<std::string> propertyValue = mDevice->getConfiguration().getString("key");
2679 ASSERT_TRUE(propertyValue.has_value())
Michael Wrightd02c5b62014-02-10 15:10:22 -08002680 << "Device should have read configuration during configuration phase.";
Harry Cuttsf13161a2023-03-08 14:15:49 +00002681 ASSERT_EQ("value", *propertyValue);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002682
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002683 ASSERT_NO_FATAL_FAILURE(mapper1.assertConfigureWasCalled());
2684 ASSERT_NO_FATAL_FAILURE(mapper2.assertConfigureWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002685
2686 // Reset
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002687 unused += mDevice->reset(ARBITRARY_TIME);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002688 ASSERT_NO_FATAL_FAILURE(mapper1.assertResetWasCalled());
2689 ASSERT_NO_FATAL_FAILURE(mapper2.assertResetWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002690
2691 NotifyDeviceResetArgs resetArgs;
2692 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
2693 ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
2694 ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
2695
2696 // Metadata.
2697 ASSERT_FALSE(mDevice->isIgnored());
2698 ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), mDevice->getSources());
2699
Siarhei Vishniakou1983a712021-06-04 19:27:09 +00002700 InputDeviceInfo info = mDevice->getDeviceInfo();
Michael Wrightd02c5b62014-02-10 15:10:22 -08002701 ASSERT_EQ(DEVICE_ID, info.getId());
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002702 ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002703 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, info.getKeyboardType());
2704 ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), info.getSources());
2705
2706 // State queries.
2707 ASSERT_EQ(AMETA_ALT_ON | AMETA_SHIFT_ON, mDevice->getMetaState())
2708 << "Should query mappers and combine meta states.";
2709
2710 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2711 << "Should return unknown key code state when source not supported.";
2712 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2713 << "Should return unknown scan code state when source not supported.";
2714 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2715 << "Should return unknown switch state when source not supported.";
2716
2717 ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, AKEYCODE_A))
2718 << "Should query mapper when source is supported.";
2719 ASSERT_EQ(AKEY_STATE_UP, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 3))
2720 << "Should query mapper when source is supported.";
2721 ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 4))
2722 << "Should query mapper when source is supported.";
2723
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002724 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2};
Michael Wrightd02c5b62014-02-10 15:10:22 -08002725 uint8_t flags[4] = { 0, 0, 0, 1 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002726 ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -08002727 << "Should do nothing when source is unsupported.";
2728 ASSERT_EQ(0, flags[0]) << "Flag should be unchanged when source is unsupported.";
2729 ASSERT_EQ(0, flags[1]) << "Flag should be unchanged when source is unsupported.";
2730 ASSERT_EQ(0, flags[2]) << "Flag should be unchanged when source is unsupported.";
2731 ASSERT_EQ(1, flags[3]) << "Flag should be unchanged when source is unsupported.";
2732
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002733 ASSERT_TRUE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -08002734 << "Should query mapper when source is supported.";
2735 ASSERT_EQ(1, flags[0]) << "Flag for supported key should be set.";
2736 ASSERT_EQ(1, flags[1]) << "Flag for supported key should be set.";
2737 ASSERT_EQ(0, flags[2]) << "Flag for unsupported key should be unchanged.";
2738 ASSERT_EQ(1, flags[3]) << "Flag for unsupported key should be unchanged.";
2739
2740 // Event handling.
2741 RawEvent event;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002742 event.deviceId = EVENTHUB_ID;
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002743 unused += mDevice->process(&event, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002744
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002745 ASSERT_NO_FATAL_FAILURE(mapper1.assertProcessWasCalled());
2746 ASSERT_NO_FATAL_FAILURE(mapper2.assertProcessWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002747}
2748
Yeabkal Wubshitb1b96db2024-01-24 12:47:00 -08002749TEST_F(InputDeviceTest, Configure_SmoothScrollViewBehaviorNotSet) {
2750 // Set some behavior to force the configuration to be update.
2751 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "1");
2752 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2753 AINPUT_SOURCE_KEYBOARD);
2754
2755 std::list<NotifyArgs> unused =
2756 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2757 /*changes=*/{});
2758
2759 ASSERT_FALSE(mDevice->getDeviceInfo().getViewBehavior().shouldSmoothScroll.has_value());
2760}
2761
2762TEST_F(InputDeviceTest, Configure_SmoothScrollViewBehaviorEnabled) {
2763 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.viewBehavior_smoothScroll", "1");
2764 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2765 AINPUT_SOURCE_KEYBOARD);
2766
2767 std::list<NotifyArgs> unused =
2768 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2769 /*changes=*/{});
2770
2771 ASSERT_TRUE(mDevice->getDeviceInfo().getViewBehavior().shouldSmoothScroll.value_or(false));
2772}
2773
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -07002774TEST_F(InputDeviceTest, WakeDevice_AddsWakeFlagToProcessNotifyArgs) {
2775 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "1");
2776 FakeInputMapper& mapper =
2777 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2778 AINPUT_SOURCE_KEYBOARD);
2779 NotifyMotionArgs args1;
2780 NotifySwitchArgs args2;
2781 NotifyKeyArgs args3;
2782 mapper.setProcessResult({args1, args2, args3});
2783
2784 InputReaderConfiguration config;
2785 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2786
2787 RawEvent event;
2788 event.deviceId = EVENTHUB_ID;
2789 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2790
2791 for (auto& arg : notifyArgs) {
2792 if (const auto notifyMotionArgs = std::get_if<NotifyMotionArgs>(&arg)) {
2793 ASSERT_EQ(POLICY_FLAG_WAKE, notifyMotionArgs->policyFlags);
2794 } else if (const auto notifySwitchArgs = std::get_if<NotifySwitchArgs>(&arg)) {
2795 ASSERT_EQ(POLICY_FLAG_WAKE, notifySwitchArgs->policyFlags);
2796 } else if (const auto notifyKeyArgs = std::get_if<NotifyKeyArgs>(&arg)) {
2797 ASSERT_EQ(POLICY_FLAG_WAKE, notifyKeyArgs->policyFlags);
2798 }
2799 }
2800}
2801
2802TEST_F(InputDeviceTest, NotWakeDevice_DoesNotAddWakeFlagToProcessNotifyArgs) {
2803 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "0");
2804 FakeInputMapper& mapper =
2805 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2806 AINPUT_SOURCE_KEYBOARD);
2807 NotifyMotionArgs args;
2808 mapper.setProcessResult({args});
2809
2810 InputReaderConfiguration config;
2811 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2812
2813 RawEvent event;
2814 event.deviceId = EVENTHUB_ID;
2815 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2816
2817 // POLICY_FLAG_WAKE is not added to the NotifyArgs.
2818 ASSERT_EQ(0u, std::get<NotifyMotionArgs>(notifyArgs.front()).policyFlags);
2819}
2820
2821TEST_F(InputDeviceTest, NotWakeDevice_DoesNotRemoveExistingWakeFlagFromProcessNotifyArgs) {
2822 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "0");
2823 FakeInputMapper& mapper =
2824 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2825 AINPUT_SOURCE_KEYBOARD);
2826 NotifyMotionArgs args;
2827 args.policyFlags = POLICY_FLAG_WAKE;
2828 mapper.setProcessResult({args});
2829
2830 InputReaderConfiguration config;
2831 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2832
2833 RawEvent event;
2834 event.deviceId = EVENTHUB_ID;
2835 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2836
2837 // The POLICY_FLAG_WAKE is preserved, despite the device being a non-wake device.
2838 ASSERT_EQ(POLICY_FLAG_WAKE, std::get<NotifyMotionArgs>(notifyArgs.front()).policyFlags);
2839}
2840
Arthur Hung2c9a3342019-07-23 14:18:59 +08002841// A single input device is associated with a specific display. Check that:
2842// 1. Device is disabled if the viewport corresponding to the associated display is not found
Arpit Singh48189772023-05-30 14:12:49 +00002843// 2. Device is disabled when configure API is called
Arthur Hung2c9a3342019-07-23 14:18:59 +08002844TEST_F(InputDeviceTest, Configure_AssignsDisplayPort) {
Arpit Singh8e6fb252023-04-06 11:49:17 +00002845 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2846 AINPUT_SOURCE_TOUCHSCREEN);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002847
2848 // First Configuration.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002849 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002850 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2851 /*changes=*/{});
Arthur Hung2c9a3342019-07-23 14:18:59 +08002852
2853 // Device should be enabled by default.
2854 ASSERT_TRUE(mDevice->isEnabled());
2855
2856 // Prepare associated info.
2857 constexpr uint8_t hdmi = 1;
2858 const std::string UNIQUE_ID = "local:1";
2859
2860 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002861 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002862 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002863 // Device should be disabled because it is associated with a specific display via
2864 // input port <-> display port association, but the corresponding display is not found
2865 ASSERT_FALSE(mDevice->isEnabled());
2866
2867 // Prepare displays.
2868 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +00002869 ui::ROTATION_0, /*isActive=*/true, UNIQUE_ID, hdmi,
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00002870 ViewportType::INTERNAL);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002871 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002872 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002873 ASSERT_TRUE(mDevice->isEnabled());
2874
2875 // Device should be disabled after set disable.
2876 mFakePolicy->addDisabledDevice(mDevice->getId());
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002877 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002878 InputReaderConfiguration::Change::ENABLED_STATE);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002879 ASSERT_FALSE(mDevice->isEnabled());
2880
2881 // Device should still be disabled even found the associated display.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002882 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002883 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002884 ASSERT_FALSE(mDevice->isEnabled());
2885}
Michael Wrightd02c5b62014-02-10 15:10:22 -08002886
Christine Franks1ba71cc2021-04-07 14:37:42 -07002887TEST_F(InputDeviceTest, Configure_AssignsDisplayUniqueId) {
2888 // Device should be enabled by default.
2889 mFakePolicy->clearViewports();
Arpit Singh8e6fb252023-04-06 11:49:17 +00002890 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2891 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002892 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002893 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2894 /*changes=*/{});
Christine Franks1ba71cc2021-04-07 14:37:42 -07002895 ASSERT_TRUE(mDevice->isEnabled());
2896
2897 // Device should be disabled because it is associated with a specific display, but the
2898 // corresponding display is not found.
Christine Franks2a2293c2022-01-18 11:51:16 -08002899 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002900 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002901 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002902 ASSERT_FALSE(mDevice->isEnabled());
2903
2904 // Device should be enabled when a display is found.
2905 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00002906 ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
Christine Franks1ba71cc2021-04-07 14:37:42 -07002907 NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002908 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002909 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002910 ASSERT_TRUE(mDevice->isEnabled());
2911
2912 // Device should be disabled after set disable.
2913 mFakePolicy->addDisabledDevice(mDevice->getId());
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002914 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002915 InputReaderConfiguration::Change::ENABLED_STATE);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002916 ASSERT_FALSE(mDevice->isEnabled());
2917
2918 // Device should still be disabled even found the associated display.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002919 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002920 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002921 ASSERT_FALSE(mDevice->isEnabled());
2922}
2923
Christine Franks2a2293c2022-01-18 11:51:16 -08002924TEST_F(InputDeviceTest, Configure_UniqueId_CorrectlyMatches) {
2925 mFakePolicy->clearViewports();
Arpit Singh8e6fb252023-04-06 11:49:17 +00002926 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2927 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002928 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002929 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2930 /*changes=*/{});
Christine Franks2a2293c2022-01-18 11:51:16 -08002931
Christine Franks2a2293c2022-01-18 11:51:16 -08002932 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
2933 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00002934 ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
Christine Franks2a2293c2022-01-18 11:51:16 -08002935 NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan55c5ee22024-02-14 06:03:02 +00002936 const auto initialGeneration = mDevice->getGeneration();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002937 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002938 InputReaderConfiguration::Change::DISPLAY_INFO);
Antonio Kantek0ac5e092024-04-22 17:10:27 +00002939 ASSERT_EQ(DISPLAY_UNIQUE_ID, mDevice->getAssociatedDisplayUniqueIdByPort());
Prabir Pradhan55c5ee22024-02-14 06:03:02 +00002940 ASSERT_GT(mDevice->getGeneration(), initialGeneration);
2941 ASSERT_EQ(mDevice->getDeviceInfo().getAssociatedDisplayId(), SECONDARY_DISPLAY_ID);
Christine Franks2a2293c2022-01-18 11:51:16 -08002942}
2943
Siarhei Vishniakou30feb8c2022-09-28 10:48:29 -07002944/**
2945 * This test reproduces a crash caused by a dangling reference that remains after device is added
2946 * and removed. The reference is accessed in InputDevice::dump(..);
2947 */
2948TEST_F(InputDeviceTest, DumpDoesNotCrash) {
2949 constexpr int32_t TEST_EVENTHUB_ID = 10;
2950 mFakeEventHub->addDevice(TEST_EVENTHUB_ID, "Test EventHub device", InputDeviceClass::BATTERY);
2951
Harry Cutts33476232023-01-30 19:57:29 +00002952 InputDevice device(mReader->getContext(), /*id=*/1, /*generation=*/2, /*identifier=*/{});
Arpit Singh82f29a12023-06-13 15:05:53 +00002953 auto _ = device.addEventHubDevice(ARBITRARY_TIME, TEST_EVENTHUB_ID,
2954 mFakePolicy->getReaderConfiguration());
Siarhei Vishniakou30feb8c2022-09-28 10:48:29 -07002955 device.removeEventHubDevice(TEST_EVENTHUB_ID);
2956 std::string dumpStr, eventHubDevStr;
2957 device.dump(dumpStr, eventHubDevStr);
2958}
2959
Prabir Pradhanb54ffb22022-10-27 18:03:34 +00002960TEST_F(InputDeviceTest, GetBluetoothAddress) {
2961 const auto& address = mReader->getBluetoothAddress(DEVICE_ID);
2962 ASSERT_TRUE(address);
2963 ASSERT_EQ(DEVICE_BLUETOOTH_ADDRESS, *address);
2964}
2965
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002966TEST_F(InputDeviceTest, KernelBufferOverflowResetsMappers) {
2967 mFakePolicy->clearViewports();
2968 FakeInputMapper& mapper =
2969 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2970 AINPUT_SOURCE_KEYBOARD);
2971 std::list<NotifyArgs> unused =
2972 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2973 /*changes=*/{});
2974
2975 mapper.assertConfigureWasCalled();
2976 mapper.assertResetWasNotCalled();
2977
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -08002978 RawEvent event{.when = ARBITRARY_TIME,
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002979 .readTime = ARBITRARY_TIME,
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -08002980 .deviceId = EVENTHUB_ID,
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002981 .type = EV_SYN,
2982 .code = SYN_REPORT,
2983 .value = 0};
2984
2985 // Events are processed normally.
2986 unused = mDevice->process(&event, /*count=*/1);
2987 mapper.assertProcessWasCalled();
2988
2989 // Simulate a kernel buffer overflow, which generates a SYN_DROPPED event.
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002990 event.type = EV_SYN;
2991 event.code = SYN_DROPPED;
2992 event.value = 0;
2993 unused = mDevice->process(&event, /*count=*/1);
2994 mapper.assertProcessWasNotCalled();
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002995
2996 // All events until the next SYN_REPORT should be dropped.
2997 event.type = EV_KEY;
2998 event.code = KEY_A;
2999 event.value = 1;
3000 unused = mDevice->process(&event, /*count=*/1);
3001 mapper.assertProcessWasNotCalled();
3002
3003 // We get the SYN_REPORT event now, which is not forwarded to mappers.
Arpit Singh4b4a4572023-11-24 18:19:56 +00003004 // This should reset the mapper.
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003005 event.type = EV_SYN;
3006 event.code = SYN_REPORT;
3007 event.value = 0;
3008 unused = mDevice->process(&event, /*count=*/1);
3009 mapper.assertProcessWasNotCalled();
Arpit Singh4b4a4572023-11-24 18:19:56 +00003010 mapper.assertResetWasCalled();
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003011
3012 // The mapper receives events normally now.
3013 event.type = EV_KEY;
3014 event.code = KEY_B;
3015 event.value = 1;
3016 unused = mDevice->process(&event, /*count=*/1);
3017 mapper.assertProcessWasCalled();
3018}
3019
Chris Yef59a2f42020-10-16 12:55:26 -07003020// --- SensorInputMapperTest ---
3021
3022class SensorInputMapperTest : public InputMapperTest {
3023protected:
3024 static const int32_t ACCEL_RAW_MIN;
3025 static const int32_t ACCEL_RAW_MAX;
3026 static const int32_t ACCEL_RAW_FUZZ;
3027 static const int32_t ACCEL_RAW_FLAT;
3028 static const int32_t ACCEL_RAW_RESOLUTION;
3029
3030 static const int32_t GYRO_RAW_MIN;
3031 static const int32_t GYRO_RAW_MAX;
3032 static const int32_t GYRO_RAW_FUZZ;
3033 static const int32_t GYRO_RAW_FLAT;
3034 static const int32_t GYRO_RAW_RESOLUTION;
3035
3036 static const float GRAVITY_MS2_UNIT;
3037 static const float DEGREE_RADIAN_UNIT;
3038
3039 void prepareAccelAxes();
3040 void prepareGyroAxes();
3041 void setAccelProperties();
3042 void setGyroProperties();
3043 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::SENSOR); }
3044};
3045
3046const int32_t SensorInputMapperTest::ACCEL_RAW_MIN = -32768;
3047const int32_t SensorInputMapperTest::ACCEL_RAW_MAX = 32768;
3048const int32_t SensorInputMapperTest::ACCEL_RAW_FUZZ = 16;
3049const int32_t SensorInputMapperTest::ACCEL_RAW_FLAT = 0;
3050const int32_t SensorInputMapperTest::ACCEL_RAW_RESOLUTION = 8192;
3051
3052const int32_t SensorInputMapperTest::GYRO_RAW_MIN = -2097152;
3053const int32_t SensorInputMapperTest::GYRO_RAW_MAX = 2097152;
3054const int32_t SensorInputMapperTest::GYRO_RAW_FUZZ = 16;
3055const int32_t SensorInputMapperTest::GYRO_RAW_FLAT = 0;
3056const int32_t SensorInputMapperTest::GYRO_RAW_RESOLUTION = 1024;
3057
3058const float SensorInputMapperTest::GRAVITY_MS2_UNIT = 9.80665f;
3059const float SensorInputMapperTest::DEGREE_RADIAN_UNIT = 0.0174533f;
3060
3061void SensorInputMapperTest::prepareAccelAxes() {
3062 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3063 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3064 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3065 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3066 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Z, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3067 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3068}
3069
3070void SensorInputMapperTest::prepareGyroAxes() {
3071 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RX, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3072 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3073 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RY, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3074 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3075 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RZ, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3076 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3077}
3078
3079void SensorInputMapperTest::setAccelProperties() {
3080 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 0, InputDeviceSensorType::ACCELEROMETER,
3081 /* sensorDataIndex */ 0);
3082 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 1, InputDeviceSensorType::ACCELEROMETER,
3083 /* sensorDataIndex */ 1);
3084 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 2, InputDeviceSensorType::ACCELEROMETER,
3085 /* sensorDataIndex */ 2);
3086 mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP);
3087 addConfigurationProperty("sensor.accelerometer.reportingMode", "0");
3088 addConfigurationProperty("sensor.accelerometer.maxDelay", "100000");
3089 addConfigurationProperty("sensor.accelerometer.minDelay", "5000");
3090 addConfigurationProperty("sensor.accelerometer.power", "1.5");
3091}
3092
3093void SensorInputMapperTest::setGyroProperties() {
3094 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 3, InputDeviceSensorType::GYROSCOPE,
3095 /* sensorDataIndex */ 0);
3096 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 4, InputDeviceSensorType::GYROSCOPE,
3097 /* sensorDataIndex */ 1);
3098 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 5, InputDeviceSensorType::GYROSCOPE,
3099 /* sensorDataIndex */ 2);
3100 mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP);
3101 addConfigurationProperty("sensor.gyroscope.reportingMode", "0");
3102 addConfigurationProperty("sensor.gyroscope.maxDelay", "100000");
3103 addConfigurationProperty("sensor.gyroscope.minDelay", "5000");
3104 addConfigurationProperty("sensor.gyroscope.power", "0.8");
3105}
3106
3107TEST_F(SensorInputMapperTest, GetSources) {
Arpit Singhfb706c32023-04-26 15:07:55 +00003108 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003109
3110 ASSERT_EQ(static_cast<uint32_t>(AINPUT_SOURCE_SENSOR), mapper.getSources());
3111}
3112
3113TEST_F(SensorInputMapperTest, ProcessAccelerometerSensor) {
3114 setAccelProperties();
3115 prepareAccelAxes();
Arpit Singhfb706c32023-04-26 15:07:55 +00003116 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003117
3118 ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::ACCELEROMETER,
3119 std::chrono::microseconds(10000),
3120 std::chrono::microseconds(0)));
Chris Yee14523a2020-12-19 13:46:00 -08003121 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003122 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, 20000);
3123 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, -20000);
3124 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Z, 40000);
3125 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000);
3126 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Chris Yef59a2f42020-10-16 12:55:26 -07003127
3128 NotifySensorArgs args;
3129 std::vector<float> values = {20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT,
3130 -20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT,
3131 40000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT};
3132
3133 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args));
3134 ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR);
3135 ASSERT_EQ(args.deviceId, DEVICE_ID);
3136 ASSERT_EQ(args.sensorType, InputDeviceSensorType::ACCELEROMETER);
3137 ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH);
3138 ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME);
3139 ASSERT_EQ(args.values, values);
3140 mapper.flushSensor(InputDeviceSensorType::ACCELEROMETER);
3141}
3142
3143TEST_F(SensorInputMapperTest, ProcessGyroscopeSensor) {
3144 setGyroProperties();
3145 prepareGyroAxes();
Arpit Singhfb706c32023-04-26 15:07:55 +00003146 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003147
3148 ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::GYROSCOPE,
3149 std::chrono::microseconds(10000),
3150 std::chrono::microseconds(0)));
Chris Yee14523a2020-12-19 13:46:00 -08003151 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003152 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RX, 20000);
3153 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RY, -20000);
3154 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RZ, 40000);
3155 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000);
3156 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Chris Yef59a2f42020-10-16 12:55:26 -07003157
3158 NotifySensorArgs args;
3159 std::vector<float> values = {20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT,
3160 -20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT,
3161 40000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT};
3162
3163 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args));
3164 ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR);
3165 ASSERT_EQ(args.deviceId, DEVICE_ID);
3166 ASSERT_EQ(args.sensorType, InputDeviceSensorType::GYROSCOPE);
3167 ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH);
3168 ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME);
3169 ASSERT_EQ(args.values, values);
3170 mapper.flushSensor(InputDeviceSensorType::GYROSCOPE);
3171}
3172
Michael Wrightd02c5b62014-02-10 15:10:22 -08003173// --- KeyboardInputMapperTest ---
3174
3175class KeyboardInputMapperTest : public InputMapperTest {
3176protected:
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003177 void SetUp() override {
3178 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
3179 InputDeviceClass::ALPHAKEY);
3180 }
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003181 const std::string UNIQUE_ID = "local:0";
Zixuan Qufecb6062022-11-12 04:44:31 +00003182 const KeyboardLayoutInfo DEVICE_KEYBOARD_LAYOUT_INFO = KeyboardLayoutInfo("en-US", "qwerty");
Michael Wrighta9cf4192022-12-01 23:46:39 +00003183 void prepareDisplay(ui::Rotation orientation);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003184
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003185 void testDPadKeyRotation(KeyboardInputMapper& mapper, int32_t originalScanCode,
Arthur Hung2c9a3342019-07-23 14:18:59 +08003186 int32_t originalKeyCode, int32_t rotatedKeyCode,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003187 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003188};
3189
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003190/* Similar to setDisplayInfoAndReconfigure, but pre-populates all parameters except for the
3191 * orientation.
3192 */
Michael Wrighta9cf4192022-12-01 23:46:39 +00003193void KeyboardInputMapperTest::prepareDisplay(ui::Rotation orientation) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003194 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
3195 NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003196}
3197
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003198void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper& mapper,
Arthur Hung2c9a3342019-07-23 14:18:59 +08003199 int32_t originalScanCode, int32_t originalKeyCode,
Linnan Li13bf76a2024-05-05 19:18:02 +08003200 int32_t rotatedKeyCode,
3201 ui::LogicalDisplayId displayId) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003202 NotifyKeyArgs args;
3203
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003204 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003205 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3206 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3207 ASSERT_EQ(originalScanCode, args.scanCode);
3208 ASSERT_EQ(rotatedKeyCode, args.keyCode);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003209 ASSERT_EQ(displayId, args.displayId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003210
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003211 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003212 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3213 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3214 ASSERT_EQ(originalScanCode, args.scanCode);
3215 ASSERT_EQ(rotatedKeyCode, args.keyCode);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003216 ASSERT_EQ(displayId, args.displayId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003217}
3218
Michael Wrightd02c5b62014-02-10 15:10:22 -08003219TEST_F(KeyboardInputMapperTest, GetSources) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003220 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003221 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003222
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003223 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003224}
3225
3226TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) {
3227 const int32_t USAGE_A = 0x070004;
3228 const int32_t USAGE_UNKNOWN = 0x07ffff;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003229 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3230 mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
Chris Yea52ade12020-08-27 16:49:20 -07003231 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, POLICY_FLAG_WAKE);
3232 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, POLICY_FLAG_WAKE);
3233 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, POLICY_FLAG_WAKE);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003234
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003235 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003236 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003237 // Initial metastate is AMETA_NONE.
3238 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003239
3240 // Key down by scan code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003241 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003242 NotifyKeyArgs args;
3243 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3244 ASSERT_EQ(DEVICE_ID, args.deviceId);
3245 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3246 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3247 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3248 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3249 ASSERT_EQ(KEY_HOME, args.scanCode);
3250 ASSERT_EQ(AMETA_NONE, args.metaState);
3251 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3252 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3253 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3254
3255 // Key up by scan code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003256 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003257 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3258 ASSERT_EQ(DEVICE_ID, args.deviceId);
3259 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3260 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3261 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3262 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3263 ASSERT_EQ(KEY_HOME, args.scanCode);
3264 ASSERT_EQ(AMETA_NONE, args.metaState);
3265 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3266 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3267 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3268
3269 // Key down by usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003270 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A);
3271 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, 0, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003272 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3273 ASSERT_EQ(DEVICE_ID, args.deviceId);
3274 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3275 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3276 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3277 ASSERT_EQ(AKEYCODE_A, args.keyCode);
3278 ASSERT_EQ(0, args.scanCode);
3279 ASSERT_EQ(AMETA_NONE, args.metaState);
3280 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3281 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3282 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3283
3284 // Key up by usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003285 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A);
3286 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003287 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3288 ASSERT_EQ(DEVICE_ID, args.deviceId);
3289 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3290 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3291 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3292 ASSERT_EQ(AKEYCODE_A, args.keyCode);
3293 ASSERT_EQ(0, args.scanCode);
3294 ASSERT_EQ(AMETA_NONE, args.metaState);
3295 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3296 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3297 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3298
3299 // Key down with unknown scan code or usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003300 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
3301 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003302 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3303 ASSERT_EQ(DEVICE_ID, args.deviceId);
3304 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3305 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3306 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3307 ASSERT_EQ(0, args.keyCode);
3308 ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
3309 ASSERT_EQ(AMETA_NONE, args.metaState);
3310 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3311 ASSERT_EQ(0U, args.policyFlags);
3312 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3313
3314 // Key up with unknown scan code or usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003315 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
3316 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_UNKNOWN, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003317 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3318 ASSERT_EQ(DEVICE_ID, args.deviceId);
3319 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3320 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3321 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3322 ASSERT_EQ(0, args.keyCode);
3323 ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
3324 ASSERT_EQ(AMETA_NONE, args.metaState);
3325 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3326 ASSERT_EQ(0U, args.policyFlags);
3327 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3328}
3329
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003330TEST_F(KeyboardInputMapperTest, Process_KeyRemapping) {
3331 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
3332 mFakeEventHub->addKey(EVENTHUB_ID, KEY_B, 0, AKEYCODE_B, 0);
3333 mFakeEventHub->addKeyRemapping(EVENTHUB_ID, AKEYCODE_A, AKEYCODE_B);
3334
3335 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003336 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003337
3338 // Key down by scan code.
3339 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_A, 1);
3340 NotifyKeyArgs args;
3341 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3342 ASSERT_EQ(AKEYCODE_B, args.keyCode);
3343
3344 // Key up by scan code.
3345 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 0);
3346 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3347 ASSERT_EQ(AKEYCODE_B, args.keyCode);
3348}
3349
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003350/**
3351 * Ensure that the readTime is set to the time when the EV_KEY is received.
3352 */
3353TEST_F(KeyboardInputMapperTest, Process_SendsReadTime) {
3354 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3355
3356 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003357 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003358 NotifyKeyArgs args;
3359
3360 // Key down
Harry Cutts33476232023-01-30 19:57:29 +00003361 process(mapper, ARBITRARY_TIME, /*readTime=*/12, EV_KEY, KEY_HOME, 1);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003362 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3363 ASSERT_EQ(12, args.readTime);
3364
3365 // Key up
Harry Cutts33476232023-01-30 19:57:29 +00003366 process(mapper, ARBITRARY_TIME, /*readTime=*/15, EV_KEY, KEY_HOME, 1);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003367 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3368 ASSERT_EQ(15, args.readTime);
3369}
3370
Michael Wrightd02c5b62014-02-10 15:10:22 -08003371TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003372 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFTSHIFT, 0, AKEYCODE_SHIFT_LEFT, 0);
3373 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
Chris Yea52ade12020-08-27 16:49:20 -07003374 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 0);
3375 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0);
3376 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003377
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003378 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003379 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003380
Arthur Hung95f68612022-04-07 14:08:22 +08003381 // Initial metastate is AMETA_NONE.
3382 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003383
3384 // Metakey down.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003385 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003386 NotifyKeyArgs args;
3387 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3388 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003389 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
arthurhungdcef2dc2020-08-11 14:47:50 +08003390 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003391
3392 // Key down.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003393 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003394 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3395 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003396 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003397
3398 // Key up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003399 process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_KEY, KEY_A, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003400 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3401 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003402 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003403
3404 // Metakey up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003405 process(mapper, ARBITRARY_TIME + 3, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003406 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3407 ASSERT_EQ(AMETA_NONE, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003408 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
arthurhungdcef2dc2020-08-11 14:47:50 +08003409 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003410}
3411
3412TEST_F(KeyboardInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateDPad) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003413 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3414 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3415 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3416 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003417
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003418 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003419 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003420
Michael Wrighta9cf4192022-12-01 23:46:39 +00003421 prepareDisplay(ui::ROTATION_90);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003422 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3423 KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
3424 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3425 KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
3426 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3427 KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
3428 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3429 KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
3430}
3431
3432TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003433 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3434 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3435 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3436 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003437
Michael Wrightd02c5b62014-02-10 15:10:22 -08003438 addConfigurationProperty("keyboard.orientationAware", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003439 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003440 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003441
Michael Wrighta9cf4192022-12-01 23:46:39 +00003442 prepareDisplay(ui::ROTATION_0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003443 ASSERT_NO_FATAL_FAILURE(
3444 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
3445 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3446 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3447 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3448 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3449 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3450 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003451
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003452 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003453 prepareDisplay(ui::ROTATION_90);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003454 ASSERT_NO_FATAL_FAILURE(
3455 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3456 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3457 AKEYCODE_DPAD_UP, DISPLAY_ID));
3458 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3459 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3460 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3461 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003462
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003463 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003464 prepareDisplay(ui::ROTATION_180);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003465 ASSERT_NO_FATAL_FAILURE(
3466 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3467 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3468 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3469 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3470 AKEYCODE_DPAD_UP, DISPLAY_ID));
3471 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3472 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003473
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003474 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003475 prepareDisplay(ui::ROTATION_270);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003476 ASSERT_NO_FATAL_FAILURE(
3477 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3478 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3479 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3480 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3481 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3482 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3483 AKEYCODE_DPAD_UP, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003484
3485 // Special case: if orientation changes while key is down, we still emit the same keycode
3486 // in the key up as we did in the key down.
3487 NotifyKeyArgs args;
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003488 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003489 prepareDisplay(ui::ROTATION_270);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003490 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003491 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3492 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3493 ASSERT_EQ(KEY_UP, args.scanCode);
3494 ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
3495
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003496 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003497 prepareDisplay(ui::ROTATION_180);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003498 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003499 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3500 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3501 ASSERT_EQ(KEY_UP, args.scanCode);
3502 ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
3503}
3504
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003505TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_NotOrientationAware) {
3506 // If the keyboard is not orientation aware,
3507 // key events should not be associated with a specific display id
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003508 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003509
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003510 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003511 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003512 NotifyKeyArgs args;
3513
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003514 // Display id should be LogicalDisplayId::INVALID without any display configuration.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003515 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003516 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003517 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003518 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003519 ASSERT_EQ(ui::LogicalDisplayId::INVALID, args.displayId);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003520
Michael Wrighta9cf4192022-12-01 23:46:39 +00003521 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003522 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003523 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003524 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003525 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003526 ASSERT_EQ(ui::LogicalDisplayId::INVALID, args.displayId);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003527}
3528
3529TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_OrientationAware) {
3530 // If the keyboard is orientation aware,
3531 // key events should be associated with the internal viewport
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003532 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003533
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003534 addConfigurationProperty("keyboard.orientationAware", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003535 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003536 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003537 NotifyKeyArgs args;
3538
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003539 // Display id should be LogicalDisplayId::INVALID without any display configuration.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003540 // ^--- already checked by the previous test
3541
Michael Wrighta9cf4192022-12-01 23:46:39 +00003542 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003543 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003544 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003545 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003546 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003547 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3548 ASSERT_EQ(DISPLAY_ID, args.displayId);
3549
Linnan Li13bf76a2024-05-05 19:18:02 +08003550 constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003551 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003552 setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003553 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003554 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003555 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003556 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003557 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3558 ASSERT_EQ(newDisplayId, args.displayId);
3559}
3560
Michael Wrightd02c5b62014-02-10 15:10:22 -08003561TEST_F(KeyboardInputMapperTest, GetKeyCodeState) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003562 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003563 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003564
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003565 mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003566 ASSERT_EQ(1, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003567
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003568 mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003569 ASSERT_EQ(0, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003570}
3571
Philip Junker4af3b3d2021-12-14 10:36:55 +01003572TEST_F(KeyboardInputMapperTest, GetKeyCodeForKeyLocation) {
3573 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003574 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Philip Junker4af3b3d2021-12-14 10:36:55 +01003575
3576 mFakeEventHub->addKeyCodeMapping(EVENTHUB_ID, AKEYCODE_Y, AKEYCODE_Z);
3577 ASSERT_EQ(AKEYCODE_Z, mapper.getKeyCodeForKeyLocation(AKEYCODE_Y))
3578 << "If a mapping is available, the result is equal to the mapping";
3579
3580 ASSERT_EQ(AKEYCODE_A, mapper.getKeyCodeForKeyLocation(AKEYCODE_A))
3581 << "If no mapping is available, the result is the key location";
3582}
3583
Michael Wrightd02c5b62014-02-10 15:10:22 -08003584TEST_F(KeyboardInputMapperTest, GetScanCodeState) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003585 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003586 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003587
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003588 mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003589 ASSERT_EQ(1, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003590
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003591 mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003592 ASSERT_EQ(0, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003593}
3594
3595TEST_F(KeyboardInputMapperTest, MarkSupportedKeyCodes) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003596 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003597 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003598
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003599 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003600
Michael Wrightd02c5b62014-02-10 15:10:22 -08003601 uint8_t flags[2] = { 0, 0 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07003602 ASSERT_TRUE(mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_A, AKEYCODE_B}, flags));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003603 ASSERT_TRUE(flags[0]);
3604 ASSERT_FALSE(flags[1]);
3605}
3606
3607TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003608 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3609 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3610 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3611 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3612 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3613 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003614
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003615 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003616 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003617 // Initial metastate is AMETA_NONE.
3618 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003619
3620 // Initialization should have turned all of the lights off.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003621 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3622 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3623 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003624
3625 // Toggle caps lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003626 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3627 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003628 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3629 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3630 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003631 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003632
3633 // Toggle num lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003634 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3635 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003636 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3637 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3638 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003639 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003640
3641 // Toggle caps lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003642 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3643 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003644 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3645 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3646 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003647 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003648
3649 // Toggle scroll lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003650 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3651 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003652 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3653 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3654 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003655 ASSERT_EQ(AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003656
3657 // Toggle num lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003658 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3659 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003660 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3661 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3662 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003663 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003664
3665 // Toggle scroll lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003666 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3667 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003668 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3669 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3670 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003671 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003672}
3673
Chris Yea52ade12020-08-27 16:49:20 -07003674TEST_F(KeyboardInputMapperTest, NoMetaStateWhenMetaKeysNotPresent) {
3675 mFakeEventHub->addKey(EVENTHUB_ID, BTN_A, 0, AKEYCODE_BUTTON_A, 0);
3676 mFakeEventHub->addKey(EVENTHUB_ID, BTN_B, 0, AKEYCODE_BUTTON_B, 0);
3677 mFakeEventHub->addKey(EVENTHUB_ID, BTN_X, 0, AKEYCODE_BUTTON_X, 0);
3678 mFakeEventHub->addKey(EVENTHUB_ID, BTN_Y, 0, AKEYCODE_BUTTON_Y, 0);
3679
3680 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003681 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Chris Yea52ade12020-08-27 16:49:20 -07003682
Chris Yea52ade12020-08-27 16:49:20 -07003683 // Meta state should be AMETA_NONE after reset
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003684 std::list<NotifyArgs> unused = mapper.reset(ARBITRARY_TIME);
Chris Yea52ade12020-08-27 16:49:20 -07003685 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3686 // Meta state should be AMETA_NONE with update, as device doesn't have the keys.
3687 mapper.updateMetaState(AKEYCODE_NUM_LOCK);
3688 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3689
3690 NotifyKeyArgs args;
3691 // Press button "A"
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003692 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_A, 1);
Chris Yea52ade12020-08-27 16:49:20 -07003693 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3694 ASSERT_EQ(AMETA_NONE, args.metaState);
3695 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3696 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3697 ASSERT_EQ(AKEYCODE_BUTTON_A, args.keyCode);
3698
3699 // Button up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003700 process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_KEY, BTN_A, 0);
Chris Yea52ade12020-08-27 16:49:20 -07003701 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3702 ASSERT_EQ(AMETA_NONE, args.metaState);
3703 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
3704 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3705 ASSERT_EQ(AKEYCODE_BUTTON_A, args.keyCode);
3706}
3707
Arthur Hung2c9a3342019-07-23 14:18:59 +08003708TEST_F(KeyboardInputMapperTest, Configure_AssignsDisplayPort) {
3709 // keyboard 1.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003710 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3711 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3712 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3713 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003714
3715 // keyboard 2.
3716 const std::string USB2 = "USB2";
arthurhungdcef2dc2020-08-11 14:47:50 +08003717 const std::string DEVICE_NAME2 = "KEYBOARD2";
Arthur Hung2c9a3342019-07-23 14:18:59 +08003718 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003719 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
arthurhungdcef2dc2020-08-11 14:47:50 +08003720 std::shared_ptr<InputDevice> device2 =
3721 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
Dominik Laskowski2f01d772022-03-23 16:01:29 -07003722 ftl::Flags<InputDeviceClass>(0));
arthurhungdcef2dc2020-08-11 14:47:50 +08003723
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003724 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3725 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3726 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3727 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003728
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003729 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003730 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003731
Arpit Singh67ca6842023-04-26 14:43:16 +00003732 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003733 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003734 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3735 mFakePolicy
3736 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003737 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003738 std::list<NotifyArgs> unused =
3739 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003740 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003741 unused += device2->reset(ARBITRARY_TIME);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003742
3743 // Prepared displays and associated info.
3744 constexpr uint8_t hdmi1 = 0;
3745 constexpr uint8_t hdmi2 = 1;
3746 const std::string SECONDARY_UNIQUE_ID = "local:1";
3747
3748 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
3749 mFakePolicy->addInputPortAssociation(USB2, hdmi2);
3750
3751 // No associated display viewport found, should disable the device.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003752 unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003753 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003754 ASSERT_FALSE(device2->isEnabled());
3755
3756 // Prepare second display.
Linnan Li13bf76a2024-05-05 19:18:02 +08003757 constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
Michael Wrighta9cf4192022-12-01 23:46:39 +00003758 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003759 UNIQUE_ID, hdmi1, ViewportType::INTERNAL);
Michael Wrighta9cf4192022-12-01 23:46:39 +00003760 setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003761 SECONDARY_UNIQUE_ID, hdmi2, ViewportType::EXTERNAL);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003762 // Default device will reconfigure above, need additional reconfiguration for another device.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003763 unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003764 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003765
3766 // Device should be enabled after the associated display is found.
3767 ASSERT_TRUE(mDevice->isEnabled());
3768 ASSERT_TRUE(device2->isEnabled());
3769
3770 // Test pad key events
3771 ASSERT_NO_FATAL_FAILURE(
3772 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
3773 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3774 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3775 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3776 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3777 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3778 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3779
3780 ASSERT_NO_FATAL_FAILURE(
3781 testDPadKeyRotation(mapper2, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, newDisplayId));
3782 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3783 AKEYCODE_DPAD_RIGHT, newDisplayId));
3784 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3785 AKEYCODE_DPAD_DOWN, newDisplayId));
3786 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3787 AKEYCODE_DPAD_LEFT, newDisplayId));
3788}
Michael Wrightd02c5b62014-02-10 15:10:22 -08003789
arthurhungc903df12020-08-11 15:08:42 +08003790TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleAfterReattach) {
3791 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3792 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3793 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3794 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3795 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3796 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3797
3798 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003799 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003800 // Initial metastate is AMETA_NONE.
3801 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
arthurhungc903df12020-08-11 15:08:42 +08003802
3803 // Initialization should have turned all of the lights off.
3804 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3805 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3806 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3807
3808 // Toggle caps lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003809 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3810 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003811 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3812 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
3813
3814 // Toggle num lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003815 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3816 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003817 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3818 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
3819
3820 // Toggle scroll lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003821 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3822 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003823 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3824 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
3825
3826 mFakeEventHub->removeDevice(EVENTHUB_ID);
3827 mReader->loopOnce();
3828
3829 // keyboard 2 should default toggle keys.
3830 const std::string USB2 = "USB2";
3831 const std::string DEVICE_NAME2 = "KEYBOARD2";
3832 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
3833 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
3834 std::shared_ptr<InputDevice> device2 =
3835 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
Dominik Laskowski2f01d772022-03-23 16:01:29 -07003836 ftl::Flags<InputDeviceClass>(0));
arthurhungc903df12020-08-11 15:08:42 +08003837 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3838 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
3839 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3840 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3841 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3842 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3843
Arpit Singh67ca6842023-04-26 14:43:16 +00003844 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
arthurhung6fe95782020-10-05 22:41:16 +08003845 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003846 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3847 mFakePolicy
3848 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003849 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003850 std::list<NotifyArgs> unused =
3851 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003852 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003853 unused += device2->reset(ARBITRARY_TIME);
arthurhungc903df12020-08-11 15:08:42 +08003854
3855 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_CAPSL));
3856 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_NUML));
3857 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_SCROLLL));
arthurhung6fe95782020-10-05 22:41:16 +08003858 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON,
3859 mapper2.getMetaState());
arthurhungc903df12020-08-11 15:08:42 +08003860}
3861
Arthur Hungcb40a002021-08-03 14:31:01 +00003862TEST_F(KeyboardInputMapperTest, Process_toggleCapsLockState) {
3863 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3864 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3865 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3866
3867 // Suppose we have two mappers. (DPAD + KEYBOARD)
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003868 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD);
Arthur Hungcb40a002021-08-03 14:31:01 +00003869 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003870 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003871 // Initial metastate is AMETA_NONE.
3872 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Arthur Hungcb40a002021-08-03 14:31:01 +00003873
3874 mReader->toggleCapsLockState(DEVICE_ID);
3875 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
3876}
3877
Arthur Hungfb3cc112022-04-13 07:39:50 +00003878TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleInMultiDevices) {
3879 // keyboard 1.
3880 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3881 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3882 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3883 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3884 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3885 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3886
3887 KeyboardInputMapper& mapper1 =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003888 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hungfb3cc112022-04-13 07:39:50 +00003889
3890 // keyboard 2.
3891 const std::string USB2 = "USB2";
3892 const std::string DEVICE_NAME2 = "KEYBOARD2";
3893 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
3894 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
3895 std::shared_ptr<InputDevice> device2 =
3896 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
3897 ftl::Flags<InputDeviceClass>(0));
3898 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3899 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
3900 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3901 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3902 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3903 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3904
Arpit Singh67ca6842023-04-26 14:43:16 +00003905 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
Arthur Hungfb3cc112022-04-13 07:39:50 +00003906 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003907 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3908 mFakePolicy
3909 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003910 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003911 std::list<NotifyArgs> unused =
3912 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003913 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003914 unused += device2->reset(ARBITRARY_TIME);
Arthur Hungfb3cc112022-04-13 07:39:50 +00003915
Arthur Hung95f68612022-04-07 14:08:22 +08003916 // Initial metastate is AMETA_NONE.
3917 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
3918 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
3919
3920 // Toggle num lock on and off.
3921 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3922 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Arthur Hungfb3cc112022-04-13 07:39:50 +00003923 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3924 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper1.getMetaState());
3925 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper2.getMetaState());
3926
3927 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3928 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
3929 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3930 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
3931 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
3932
3933 // Toggle caps lock on and off.
3934 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3935 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
3936 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3937 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper1.getMetaState());
3938 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper2.getMetaState());
3939
3940 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3941 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
3942 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3943 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
3944 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
3945
3946 // Toggle scroll lock on and off.
3947 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3948 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
3949 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3950 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper1.getMetaState());
3951 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper2.getMetaState());
3952
3953 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3954 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
3955 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3956 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
3957 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
3958}
3959
Arthur Hung2141d542022-08-23 07:45:21 +00003960TEST_F(KeyboardInputMapperTest, Process_DisabledDevice) {
3961 const int32_t USAGE_A = 0x070004;
3962 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3963 mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
3964
3965 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003966 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung2141d542022-08-23 07:45:21 +00003967 // Key down by scan code.
3968 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
3969 NotifyKeyArgs args;
3970 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3971 ASSERT_EQ(DEVICE_ID, args.deviceId);
3972 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3973 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3974 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3975 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3976 ASSERT_EQ(KEY_HOME, args.scanCode);
3977 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3978
3979 // Disable device, it should synthesize cancellation events for down events.
3980 mFakePolicy->addDisabledDevice(DEVICE_ID);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003981 configureDevice(InputReaderConfiguration::Change::ENABLED_STATE);
Arthur Hung2141d542022-08-23 07:45:21 +00003982
3983 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3984 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3985 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3986 ASSERT_EQ(KEY_HOME, args.scanCode);
3987 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_CANCELED, args.flags);
3988}
3989
Zixuan Qufecb6062022-11-12 04:44:31 +00003990TEST_F(KeyboardInputMapperTest, Configure_AssignKeyboardLayoutInfo) {
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003991 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Zixuan Qufecb6062022-11-12 04:44:31 +00003992 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003993 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
3994 /*changes=*/{});
Zixuan Qufecb6062022-11-12 04:44:31 +00003995
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +00003996 uint32_t generation = mReader->getContext()->getGeneration();
Zixuan Qufecb6062022-11-12 04:44:31 +00003997 mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
3998
3999 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004000 InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
Zixuan Qufecb6062022-11-12 04:44:31 +00004001
4002 InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
4003 ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.languageTag,
4004 deviceInfo.getKeyboardLayoutInfo()->languageTag);
4005 ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.layoutType,
4006 deviceInfo.getKeyboardLayoutInfo()->layoutType);
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +00004007 ASSERT_TRUE(mReader->getContext()->getGeneration() != generation);
4008
4009 // Call change layout association with the same values: Generation shouldn't change
4010 generation = mReader->getContext()->getGeneration();
4011 mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
4012 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
4013 InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
4014 ASSERT_TRUE(mReader->getContext()->getGeneration() == generation);
Zixuan Qufecb6062022-11-12 04:44:31 +00004015}
4016
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004017TEST_F(KeyboardInputMapperTest, LayoutInfoCorrectlyMapped) {
4018 mFakeEventHub->setRawLayoutInfo(EVENTHUB_ID,
4019 RawLayoutInfo{.languageTag = "en", .layoutType = "extended"});
4020
4021 // Configuration
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004022 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004023 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00004024 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00004025
4026 ASSERT_EQ("en", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->languageTag);
4027 ASSERT_EQ("extended", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->layoutType);
4028}
4029
Justin Chung71ddb432023-03-27 04:29:07 +00004030TEST_F(KeyboardInputMapperTest, Process_GesureEventToSetFlagKeepTouchMode) {
4031 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, POLICY_FLAG_GESTURE);
4032 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004033 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Justin Chung71ddb432023-03-27 04:29:07 +00004034 NotifyKeyArgs args;
4035
4036 // Key down
4037 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFT, 1);
4038 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4039 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_KEEP_TOUCH_MODE, args.flags);
4040}
4041
Prabir Pradhan38636652024-07-23 21:59:36 +00004042/**
4043 * When there is more than one KeyboardInputMapper for an InputDevice, each mapper should produce
4044 * events that use the shared keyboard source across all mappers. This is to ensure that each
4045 * input device generates key events in a consistent manner, regardless of which mapper produces
4046 * the event.
4047 */
4048TEST_F(KeyboardInputMapperTest, UsesSharedKeyboardSource) {
4049 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4050
4051 // Add a mapper with SOURCE_KEYBOARD
4052 KeyboardInputMapper& keyboardMapper =
4053 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
4054
4055 process(keyboardMapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1);
4056 ASSERT_NO_FATAL_FAILURE(
4057 mFakeListener->assertNotifyKeyWasCalled(WithSource(AINPUT_SOURCE_KEYBOARD)));
4058 process(keyboardMapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0);
4059 ASSERT_NO_FATAL_FAILURE(
4060 mFakeListener->assertNotifyKeyWasCalled(WithSource(AINPUT_SOURCE_KEYBOARD)));
4061
4062 // Add a mapper with SOURCE_DPAD
4063 KeyboardInputMapper& dpadMapper =
4064 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD);
4065 for (auto* mapper : {&keyboardMapper, &dpadMapper}) {
4066 process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1);
4067 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
4068 WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD)));
4069 process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0);
4070 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
4071 WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD)));
4072 }
4073
4074 // Add a mapper with SOURCE_GAMEPAD
4075 KeyboardInputMapper& gamepadMapper =
4076 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_GAMEPAD);
4077 for (auto* mapper : {&keyboardMapper, &dpadMapper, &gamepadMapper}) {
4078 process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1);
4079 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
4080 WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD)));
4081 process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0);
4082 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
4083 WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD)));
4084 }
4085}
4086
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004087// --- KeyboardInputMapperTest_ExternalAlphabeticDevice ---
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004088
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004089class KeyboardInputMapperTest_ExternalAlphabeticDevice : public InputMapperTest {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004090protected:
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004091 void SetUp() override {
4092 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
4093 InputDeviceClass::ALPHAKEY | InputDeviceClass::EXTERNAL);
4094 }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004095};
4096
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004097// --- KeyboardInputMapperTest_ExternalNonAlphabeticDevice ---
4098
4099class KeyboardInputMapperTest_ExternalNonAlphabeticDevice : public InputMapperTest {
4100protected:
4101 void SetUp() override {
4102 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
4103 InputDeviceClass::EXTERNAL);
4104 }
4105};
4106
4107TEST_F(KeyboardInputMapperTest_ExternalAlphabeticDevice, WakeBehavior_AlphabeticKeyboard) {
Vaibhav Devmurari16257862023-03-06 10:06:32 +00004108 // For external devices, keys will trigger wake on key down. Media keys should also trigger
4109 // wake if triggered from external devices.
Powei Fengd041c5d2019-05-03 17:11:33 -07004110
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004111 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, 0);
4112 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
4113 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
4114 POLICY_FLAG_WAKE);
Powei Fengd041c5d2019-05-03 17:11:33 -07004115
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004116 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004117 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Powei Fengd041c5d2019-05-03 17:11:33 -07004118
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004119 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004120 NotifyKeyArgs args;
4121 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4122 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4123
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004124 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004125 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4126 ASSERT_EQ(uint32_t(0), args.policyFlags);
4127
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004128 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004129 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Vaibhav Devmurari16257862023-03-06 10:06:32 +00004130 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
Powei Fengd041c5d2019-05-03 17:11:33 -07004131
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004132 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004133 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4134 ASSERT_EQ(uint32_t(0), args.policyFlags);
4135
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004136 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004137 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4138 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4139
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004140 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004141 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4142 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4143}
4144
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004145TEST_F(KeyboardInputMapperTest_ExternalNonAlphabeticDevice, WakeBehavior_NonAlphabeticKeyboard) {
Vaibhav Devmurari2681a812024-01-11 00:15:35 +00004146 // For external devices, keys will trigger wake on key down. Media keys should not trigger
4147 // wake if triggered from external non-alphaebtic keyboard (e.g. headsets).
4148
4149 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
4150 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
4151 POLICY_FLAG_WAKE);
4152
4153 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004154 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmurari2681a812024-01-11 00:15:35 +00004155
4156 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
4157 NotifyKeyArgs args;
4158 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4159 ASSERT_EQ(uint32_t(0), args.policyFlags);
4160
4161 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
4162 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4163 ASSERT_EQ(uint32_t(0), args.policyFlags);
4164
4165 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1);
4166 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4167 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4168
4169 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0);
4170 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4171 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4172}
4173
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004174TEST_F(KeyboardInputMapperTest_ExternalAlphabeticDevice, DoNotWakeByDefaultBehavior) {
Powei Fengd041c5d2019-05-03 17:11:33 -07004175 // Tv Remote key's wake behavior is prescribed by the keylayout file.
Powei Fengd041c5d2019-05-03 17:11:33 -07004176
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004177 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4178 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
4179 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, POLICY_FLAG_WAKE);
Powei Fengd041c5d2019-05-03 17:11:33 -07004180
Powei Fengd041c5d2019-05-03 17:11:33 -07004181 addConfigurationProperty("keyboard.doNotWakeByDefault", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004182 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004183 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Powei Fengd041c5d2019-05-03 17:11:33 -07004184
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004185 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004186 NotifyKeyArgs args;
4187 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4188 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4189
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004190 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004191 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4192 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4193
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004194 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_DOWN, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004195 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4196 ASSERT_EQ(uint32_t(0), args.policyFlags);
4197
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004198 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_DOWN, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004199 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4200 ASSERT_EQ(uint32_t(0), args.policyFlags);
4201
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004202 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004203 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4204 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4205
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004206 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004207 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4208 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4209}
4210
Michael Wrightd02c5b62014-02-10 15:10:22 -08004211// --- TouchInputMapperTest ---
4212
4213class TouchInputMapperTest : public InputMapperTest {
4214protected:
4215 static const int32_t RAW_X_MIN;
4216 static const int32_t RAW_X_MAX;
4217 static const int32_t RAW_Y_MIN;
4218 static const int32_t RAW_Y_MAX;
4219 static const int32_t RAW_TOUCH_MIN;
4220 static const int32_t RAW_TOUCH_MAX;
4221 static const int32_t RAW_TOOL_MIN;
4222 static const int32_t RAW_TOOL_MAX;
4223 static const int32_t RAW_PRESSURE_MIN;
4224 static const int32_t RAW_PRESSURE_MAX;
4225 static const int32_t RAW_ORIENTATION_MIN;
4226 static const int32_t RAW_ORIENTATION_MAX;
4227 static const int32_t RAW_DISTANCE_MIN;
4228 static const int32_t RAW_DISTANCE_MAX;
4229 static const int32_t RAW_TILT_MIN;
4230 static const int32_t RAW_TILT_MAX;
4231 static const int32_t RAW_ID_MIN;
4232 static const int32_t RAW_ID_MAX;
4233 static const int32_t RAW_SLOT_MIN;
4234 static const int32_t RAW_SLOT_MAX;
4235 static const float X_PRECISION;
4236 static const float Y_PRECISION;
Santos Cordonfa5cf462017-04-05 10:37:00 -07004237 static const float X_PRECISION_VIRTUAL;
4238 static const float Y_PRECISION_VIRTUAL;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004239
4240 static const float GEOMETRIC_SCALE;
Jason Gerecke489fda82012-09-07 17:19:40 -07004241 static const TouchAffineTransformation AFFINE_TRANSFORM;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004242
4243 static const VirtualKeyDefinition VIRTUAL_KEYS[2];
4244
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07004245 const std::string UNIQUE_ID = "local:0";
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004246 const std::string SECONDARY_UNIQUE_ID = "local:1";
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07004247
Michael Wrightd02c5b62014-02-10 15:10:22 -08004248 enum Axes {
4249 POSITION = 1 << 0,
4250 TOUCH = 1 << 1,
4251 TOOL = 1 << 2,
4252 PRESSURE = 1 << 3,
4253 ORIENTATION = 1 << 4,
4254 MINOR = 1 << 5,
4255 ID = 1 << 6,
4256 DISTANCE = 1 << 7,
4257 TILT = 1 << 8,
4258 SLOT = 1 << 9,
4259 TOOL_TYPE = 1 << 10,
4260 };
4261
Michael Wrighta9cf4192022-12-01 23:46:39 +00004262 void prepareDisplay(ui::Rotation orientation, std::optional<uint8_t> port = NO_PORT);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004263 void prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port = NO_PORT);
Michael Wrighta9cf4192022-12-01 23:46:39 +00004264 void prepareVirtualDisplay(ui::Rotation orientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004265 void prepareVirtualKeys();
Jason Gerecke489fda82012-09-07 17:19:40 -07004266 void prepareLocationCalibration();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004267 int32_t toRawX(float displayX);
4268 int32_t toRawY(float displayY);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07004269 int32_t toRotatedRawX(float displayX);
4270 int32_t toRotatedRawY(float displayY);
Jason Gerecke489fda82012-09-07 17:19:40 -07004271 float toCookedX(float rawX, float rawY);
4272 float toCookedY(float rawX, float rawY);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004273 float toDisplayX(int32_t rawX);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004274 float toDisplayX(int32_t rawX, int32_t displayWidth);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004275 float toDisplayY(int32_t rawY);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004276 float toDisplayY(int32_t rawY, int32_t displayHeight);
4277
Michael Wrightd02c5b62014-02-10 15:10:22 -08004278};
4279
4280const int32_t TouchInputMapperTest::RAW_X_MIN = 25;
4281const int32_t TouchInputMapperTest::RAW_X_MAX = 1019;
4282const int32_t TouchInputMapperTest::RAW_Y_MIN = 30;
4283const int32_t TouchInputMapperTest::RAW_Y_MAX = 1009;
4284const int32_t TouchInputMapperTest::RAW_TOUCH_MIN = 0;
4285const int32_t TouchInputMapperTest::RAW_TOUCH_MAX = 31;
4286const int32_t TouchInputMapperTest::RAW_TOOL_MIN = 0;
4287const int32_t TouchInputMapperTest::RAW_TOOL_MAX = 15;
Michael Wrightaa449c92017-12-13 21:21:43 +00004288const int32_t TouchInputMapperTest::RAW_PRESSURE_MIN = 0;
4289const int32_t TouchInputMapperTest::RAW_PRESSURE_MAX = 255;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004290const int32_t TouchInputMapperTest::RAW_ORIENTATION_MIN = -7;
4291const int32_t TouchInputMapperTest::RAW_ORIENTATION_MAX = 7;
4292const int32_t TouchInputMapperTest::RAW_DISTANCE_MIN = 0;
4293const int32_t TouchInputMapperTest::RAW_DISTANCE_MAX = 7;
4294const int32_t TouchInputMapperTest::RAW_TILT_MIN = 0;
4295const int32_t TouchInputMapperTest::RAW_TILT_MAX = 150;
4296const int32_t TouchInputMapperTest::RAW_ID_MIN = 0;
4297const int32_t TouchInputMapperTest::RAW_ID_MAX = 9;
4298const int32_t TouchInputMapperTest::RAW_SLOT_MIN = 0;
4299const int32_t TouchInputMapperTest::RAW_SLOT_MAX = 9;
4300const float TouchInputMapperTest::X_PRECISION = float(RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH;
4301const float TouchInputMapperTest::Y_PRECISION = float(RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT;
Santos Cordonfa5cf462017-04-05 10:37:00 -07004302const float TouchInputMapperTest::X_PRECISION_VIRTUAL =
4303 float(RAW_X_MAX - RAW_X_MIN + 1) / VIRTUAL_DISPLAY_WIDTH;
4304const float TouchInputMapperTest::Y_PRECISION_VIRTUAL =
4305 float(RAW_Y_MAX - RAW_Y_MIN + 1) / VIRTUAL_DISPLAY_HEIGHT;
Jason Gerecke489fda82012-09-07 17:19:40 -07004306const TouchAffineTransformation TouchInputMapperTest::AFFINE_TRANSFORM =
4307 TouchAffineTransformation(1, -2, 3, -4, 5, -6);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004308
4309const float TouchInputMapperTest::GEOMETRIC_SCALE =
4310 avg(float(DISPLAY_WIDTH) / (RAW_X_MAX - RAW_X_MIN + 1),
4311 float(DISPLAY_HEIGHT) / (RAW_Y_MAX - RAW_Y_MIN + 1));
4312
4313const VirtualKeyDefinition TouchInputMapperTest::VIRTUAL_KEYS[2] = {
4314 { KEY_HOME, 60, DISPLAY_HEIGHT + 15, 20, 20 },
4315 { KEY_MENU, DISPLAY_HEIGHT - 60, DISPLAY_WIDTH + 15, 20, 20 },
4316};
4317
Michael Wrighta9cf4192022-12-01 23:46:39 +00004318void TouchInputMapperTest::prepareDisplay(ui::Rotation orientation, std::optional<uint8_t> port) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01004319 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
4320 port, ViewportType::INTERNAL);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004321}
4322
4323void TouchInputMapperTest::prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port) {
4324 setDisplayInfoAndReconfigure(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00004325 ui::ROTATION_0, SECONDARY_UNIQUE_ID, port, type);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004326}
4327
Michael Wrighta9cf4192022-12-01 23:46:39 +00004328void TouchInputMapperTest::prepareVirtualDisplay(ui::Rotation orientation) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01004329 setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH, VIRTUAL_DISPLAY_HEIGHT,
4330 orientation, VIRTUAL_DISPLAY_UNIQUE_ID, NO_PORT,
4331 ViewportType::VIRTUAL);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004332}
4333
Michael Wrightd02c5b62014-02-10 15:10:22 -08004334void TouchInputMapperTest::prepareVirtualKeys() {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004335 mFakeEventHub->addVirtualKeyDefinition(EVENTHUB_ID, VIRTUAL_KEYS[0]);
4336 mFakeEventHub->addVirtualKeyDefinition(EVENTHUB_ID, VIRTUAL_KEYS[1]);
4337 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4338 mFakeEventHub->addKey(EVENTHUB_ID, KEY_MENU, 0, AKEYCODE_MENU, POLICY_FLAG_WAKE);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004339}
4340
Jason Gerecke489fda82012-09-07 17:19:40 -07004341void TouchInputMapperTest::prepareLocationCalibration() {
4342 mFakePolicy->setTouchAffineTransformation(AFFINE_TRANSFORM);
4343}
4344
Michael Wrightd02c5b62014-02-10 15:10:22 -08004345int32_t TouchInputMapperTest::toRawX(float displayX) {
4346 return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH + RAW_X_MIN);
4347}
4348
4349int32_t TouchInputMapperTest::toRawY(float displayY) {
4350 return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT + RAW_Y_MIN);
4351}
4352
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07004353int32_t TouchInputMapperTest::toRotatedRawX(float displayX) {
4354 return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_HEIGHT + RAW_X_MIN);
4355}
4356
4357int32_t TouchInputMapperTest::toRotatedRawY(float displayY) {
4358 return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_WIDTH + RAW_Y_MIN);
4359}
4360
Jason Gerecke489fda82012-09-07 17:19:40 -07004361float TouchInputMapperTest::toCookedX(float rawX, float rawY) {
4362 AFFINE_TRANSFORM.applyTo(rawX, rawY);
4363 return rawX;
4364}
4365
4366float TouchInputMapperTest::toCookedY(float rawX, float rawY) {
4367 AFFINE_TRANSFORM.applyTo(rawX, rawY);
4368 return rawY;
4369}
4370
Michael Wrightd02c5b62014-02-10 15:10:22 -08004371float TouchInputMapperTest::toDisplayX(int32_t rawX) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004372 return toDisplayX(rawX, DISPLAY_WIDTH);
4373}
4374
4375float TouchInputMapperTest::toDisplayX(int32_t rawX, int32_t displayWidth) {
4376 return float(rawX - RAW_X_MIN) * displayWidth / (RAW_X_MAX - RAW_X_MIN + 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004377}
4378
4379float TouchInputMapperTest::toDisplayY(int32_t rawY) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004380 return toDisplayY(rawY, DISPLAY_HEIGHT);
4381}
4382
4383float TouchInputMapperTest::toDisplayY(int32_t rawY, int32_t displayHeight) {
4384 return float(rawY - RAW_Y_MIN) * displayHeight / (RAW_Y_MAX - RAW_Y_MIN + 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004385}
4386
4387
4388// --- SingleTouchInputMapperTest ---
4389
4390class SingleTouchInputMapperTest : public TouchInputMapperTest {
4391protected:
4392 void prepareButtons();
4393 void prepareAxes(int axes);
4394
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004395 std::list<NotifyArgs> processDown(SingleTouchInputMapper& mapper, int32_t x, int32_t y);
4396 std::list<NotifyArgs> processMove(SingleTouchInputMapper& mapper, int32_t x, int32_t y);
4397 std::list<NotifyArgs> processUp(SingleTouchInputMapper& mappery);
4398 std::list<NotifyArgs> processPressure(SingleTouchInputMapper& mapper, int32_t pressure);
4399 std::list<NotifyArgs> processToolMajor(SingleTouchInputMapper& mapper, int32_t toolMajor);
4400 std::list<NotifyArgs> processDistance(SingleTouchInputMapper& mapper, int32_t distance);
4401 std::list<NotifyArgs> processTilt(SingleTouchInputMapper& mapper, int32_t tiltX, int32_t tiltY);
4402 std::list<NotifyArgs> processKey(SingleTouchInputMapper& mapper, int32_t code, int32_t value);
4403 std::list<NotifyArgs> processSync(SingleTouchInputMapper& mapper);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004404};
4405
4406void SingleTouchInputMapperTest::prepareButtons() {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004407 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004408}
4409
4410void SingleTouchInputMapperTest::prepareAxes(int axes) {
4411 if (axes & POSITION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004412 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
4413 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004414 }
4415 if (axes & PRESSURE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004416 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_PRESSURE, RAW_PRESSURE_MIN,
4417 RAW_PRESSURE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004418 }
4419 if (axes & TOOL) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004420 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TOOL_WIDTH, RAW_TOOL_MIN, RAW_TOOL_MAX, 0,
4421 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004422 }
4423 if (axes & DISTANCE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004424 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_DISTANCE, RAW_DISTANCE_MIN,
4425 RAW_DISTANCE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004426 }
4427 if (axes & TILT) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004428 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TILT_X, RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
4429 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TILT_Y, RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004430 }
4431}
4432
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004433std::list<NotifyArgs> SingleTouchInputMapperTest::processDown(SingleTouchInputMapper& mapper,
4434 int32_t x, int32_t y) {
4435 std::list<NotifyArgs> args;
4436 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
4437 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, x);
4438 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, y);
4439 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004440}
4441
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004442std::list<NotifyArgs> SingleTouchInputMapperTest::processMove(SingleTouchInputMapper& mapper,
4443 int32_t x, int32_t y) {
4444 std::list<NotifyArgs> args;
4445 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, x);
4446 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, y);
4447 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004448}
4449
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004450std::list<NotifyArgs> SingleTouchInputMapperTest::processUp(SingleTouchInputMapper& mapper) {
4451 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004452}
4453
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004454std::list<NotifyArgs> SingleTouchInputMapperTest::processPressure(SingleTouchInputMapper& mapper,
4455 int32_t pressure) {
4456 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_PRESSURE, pressure);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004457}
4458
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004459std::list<NotifyArgs> SingleTouchInputMapperTest::processToolMajor(SingleTouchInputMapper& mapper,
4460 int32_t toolMajor) {
4461 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TOOL_WIDTH, toolMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004462}
4463
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004464std::list<NotifyArgs> SingleTouchInputMapperTest::processDistance(SingleTouchInputMapper& mapper,
4465 int32_t distance) {
4466 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_DISTANCE, distance);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004467}
4468
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004469std::list<NotifyArgs> SingleTouchInputMapperTest::processTilt(SingleTouchInputMapper& mapper,
4470 int32_t tiltX, int32_t tiltY) {
4471 std::list<NotifyArgs> args;
4472 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TILT_X, tiltX);
4473 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TILT_Y, tiltY);
4474 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004475}
4476
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004477std::list<NotifyArgs> SingleTouchInputMapperTest::processKey(SingleTouchInputMapper& mapper,
4478 int32_t code, int32_t value) {
4479 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004480}
4481
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004482std::list<NotifyArgs> SingleTouchInputMapperTest::processSync(SingleTouchInputMapper& mapper) {
4483 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004484}
4485
Michael Wrightd02c5b62014-02-10 15:10:22 -08004486TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndNotACursor_ReturnsPointer) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004487 prepareButtons();
4488 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00004489 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004490
Josep del Río2d8c79a2023-01-23 19:33:50 +00004491 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004492}
4493
Michael Wrightd02c5b62014-02-10 15:10:22 -08004494TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004495 prepareButtons();
4496 prepareAxes(POSITION);
4497 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00004498 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004499
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004500 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004501}
4502
4503TEST_F(SingleTouchInputMapperTest, GetKeyCodeState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004504 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004505 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004506 prepareButtons();
4507 prepareAxes(POSITION);
4508 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004509 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004510
4511 // Unknown key.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004512 ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004513
4514 // Virtual key is down.
4515 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4516 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4517 processDown(mapper, x, y);
4518 processSync(mapper);
4519 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4520
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004521 ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004522
4523 // Virtual key is up.
4524 processUp(mapper);
4525 processSync(mapper);
4526 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4527
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004528 ASSERT_EQ(AKEY_STATE_UP, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004529}
4530
4531TEST_F(SingleTouchInputMapperTest, GetScanCodeState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004532 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004533 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004534 prepareButtons();
4535 prepareAxes(POSITION);
4536 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004537 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004538
4539 // Unknown key.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004540 ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004541
4542 // Virtual key is down.
4543 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4544 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4545 processDown(mapper, x, y);
4546 processSync(mapper);
4547 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4548
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004549 ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004550
4551 // Virtual key is up.
4552 processUp(mapper);
4553 processSync(mapper);
4554 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4555
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004556 ASSERT_EQ(AKEY_STATE_UP, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004557}
4558
4559TEST_F(SingleTouchInputMapperTest, MarkSupportedKeyCodes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004560 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004561 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004562 prepareButtons();
4563 prepareAxes(POSITION);
4564 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004565 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004566
Michael Wrightd02c5b62014-02-10 15:10:22 -08004567 uint8_t flags[2] = { 0, 0 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07004568 ASSERT_TRUE(
4569 mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_HOME, AKEYCODE_A}, flags));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004570 ASSERT_TRUE(flags[0]);
4571 ASSERT_FALSE(flags[1]);
4572}
4573
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004574TEST_F(SingleTouchInputMapperTest, DeviceTypeChange_RecalculatesRawToDisplayTransform) {
4575 prepareDisplay(ui::ROTATION_0);
4576 prepareAxes(POSITION);
4577 addConfigurationProperty("touch.deviceType", "touchScreen");
4578 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
4579
4580 const int32_t x = 900;
4581 const int32_t y = 75;
4582 std::list<NotifyArgs> args;
4583 args += processDown(mapper, x, y);
4584 args += processSync(mapper);
4585
4586 // Assert that motion event is received in display coordinate space for deviceType touchScreen.
4587 ASSERT_THAT(args,
4588 ElementsAre(VariantWith<NotifyMotionArgs>(
4589 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4590 WithCoords(toDisplayX(x), toDisplayY(y))))));
4591
4592 // Add device type association after the device was created.
4593 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
4594 // Send update to the mapper.
4595 std::list<NotifyArgs> unused =
4596 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
4597 InputReaderConfiguration::Change::DEVICE_TYPE /*changes*/);
4598
4599 args.clear();
4600 args += processDown(mapper, x, y);
4601 args += processSync(mapper);
4602
4603 // Assert that motion event is received in raw coordinate space for deviceType touchNavigation.
4604 ASSERT_THAT(args,
4605 ElementsAre(VariantWith<NotifyMotionArgs>(
4606 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4607 WithCoords(x - RAW_X_MIN, y - RAW_Y_MIN)))));
4608}
4609
Michael Wrightd02c5b62014-02-10 15:10:22 -08004610TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNormally_SendsKeyDownAndKeyUp) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004611 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004612 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004613 prepareButtons();
4614 prepareAxes(POSITION);
4615 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004616 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004617
arthurhungdcef2dc2020-08-11 14:47:50 +08004618 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004619
4620 NotifyKeyArgs args;
4621
4622 // Press virtual key.
4623 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4624 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4625 processDown(mapper, x, y);
4626 processSync(mapper);
4627
4628 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4629 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4630 ASSERT_EQ(DEVICE_ID, args.deviceId);
4631 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4632 ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
4633 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
4634 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
4635 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4636 ASSERT_EQ(KEY_HOME, args.scanCode);
4637 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
4638 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
4639
4640 // Release virtual key.
4641 processUp(mapper);
4642 processSync(mapper);
4643
4644 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4645 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4646 ASSERT_EQ(DEVICE_ID, args.deviceId);
4647 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4648 ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
4649 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
4650 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
4651 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4652 ASSERT_EQ(KEY_HOME, args.scanCode);
4653 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
4654 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
4655
4656 // Should not have sent any motions.
4657 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4658}
4659
4660TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfBounds_SendsKeyDownAndKeyCancel) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004661 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004662 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004663 prepareButtons();
4664 prepareAxes(POSITION);
4665 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004666 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004667
arthurhungdcef2dc2020-08-11 14:47:50 +08004668 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004669
4670 NotifyKeyArgs keyArgs;
4671
4672 // Press virtual key.
4673 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4674 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4675 processDown(mapper, x, y);
4676 processSync(mapper);
4677
4678 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
4679 ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
4680 ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
4681 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
4682 ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
4683 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
4684 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, keyArgs.flags);
4685 ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
4686 ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
4687 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
4688 ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
4689
4690 // Move out of bounds. This should generate a cancel and a pointer down since we moved
4691 // into the display area.
4692 y -= 100;
4693 processMove(mapper, x, y);
4694 processSync(mapper);
4695
4696 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
4697 ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
4698 ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
4699 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
4700 ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
4701 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
4702 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
4703 | AKEY_EVENT_FLAG_CANCELED, keyArgs.flags);
4704 ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
4705 ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
4706 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
4707 ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
4708
4709 NotifyMotionArgs motionArgs;
4710 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4711 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4712 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4713 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4714 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4715 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4716 ASSERT_EQ(0, motionArgs.flags);
4717 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4718 ASSERT_EQ(0, motionArgs.buttonState);
4719 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004720 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004721 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004722 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004723 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4724 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4725 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4726 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4727 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4728
4729 // Keep moving out of bounds. Should generate a pointer move.
4730 y -= 50;
4731 processMove(mapper, x, y);
4732 processSync(mapper);
4733
4734 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4735 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4736 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4737 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4738 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4739 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
4740 ASSERT_EQ(0, motionArgs.flags);
4741 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4742 ASSERT_EQ(0, motionArgs.buttonState);
4743 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004744 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004745 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004746 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004747 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4748 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4749 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4750 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4751 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4752
4753 // Release out of bounds. Should generate a pointer up.
4754 processUp(mapper);
4755 processSync(mapper);
4756
4757 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4758 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4759 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4760 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4761 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4762 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4763 ASSERT_EQ(0, motionArgs.flags);
4764 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4765 ASSERT_EQ(0, motionArgs.buttonState);
4766 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004767 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004768 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004769 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004770 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4771 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4772 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4773 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4774 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4775
4776 // Should not have sent any more keys or motions.
4777 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4778 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4779}
4780
4781TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMovesIn_SendsDownAsTouchEntersDisplay) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004782 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004783 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004784 prepareButtons();
4785 prepareAxes(POSITION);
4786 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004787 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004788
arthurhungdcef2dc2020-08-11 14:47:50 +08004789 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004790
4791 NotifyMotionArgs motionArgs;
4792
4793 // Initially go down out of bounds.
4794 int32_t x = -10;
4795 int32_t y = -10;
4796 processDown(mapper, x, y);
4797 processSync(mapper);
4798
4799 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4800
4801 // Move into the display area. Should generate a pointer down.
4802 x = 50;
4803 y = 75;
4804 processMove(mapper, x, y);
4805 processSync(mapper);
4806
4807 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4808 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4809 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4810 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4811 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4812 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4813 ASSERT_EQ(0, motionArgs.flags);
4814 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4815 ASSERT_EQ(0, motionArgs.buttonState);
4816 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004817 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004818 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004819 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004820 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4821 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4822 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4823 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4824 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4825
4826 // Release. Should generate a pointer up.
4827 processUp(mapper);
4828 processSync(mapper);
4829
4830 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4831 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4832 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4833 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4834 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4835 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4836 ASSERT_EQ(0, motionArgs.flags);
4837 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4838 ASSERT_EQ(0, motionArgs.buttonState);
4839 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004840 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004841 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004842 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004843 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4844 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4845 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4846 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4847 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4848
4849 // Should not have sent any more keys or motions.
4850 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4851 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4852}
4853
Santos Cordonfa5cf462017-04-05 10:37:00 -07004854TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture_VirtualDisplay) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004855 addConfigurationProperty("touch.deviceType", "touchScreen");
4856 addConfigurationProperty("touch.displayId", VIRTUAL_DISPLAY_UNIQUE_ID);
4857
Michael Wrighta9cf4192022-12-01 23:46:39 +00004858 prepareVirtualDisplay(ui::ROTATION_0);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004859 prepareButtons();
4860 prepareAxes(POSITION);
4861 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004862 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Santos Cordonfa5cf462017-04-05 10:37:00 -07004863
arthurhungdcef2dc2020-08-11 14:47:50 +08004864 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004865
4866 NotifyMotionArgs motionArgs;
4867
4868 // Down.
4869 int32_t x = 100;
4870 int32_t y = 125;
4871 processDown(mapper, x, y);
4872 processSync(mapper);
4873
4874 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4875 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4876 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4877 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4878 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4879 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4880 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4881 ASSERT_EQ(0, motionArgs.flags);
4882 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4883 ASSERT_EQ(0, motionArgs.buttonState);
4884 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004885 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004886 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004887 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004888 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4889 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4890 1, 0, 0, 0, 0, 0, 0, 0));
4891 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4892 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4893 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4894
4895 // Move.
4896 x += 50;
4897 y += 75;
4898 processMove(mapper, x, y);
4899 processSync(mapper);
4900
4901 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4902 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4903 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4904 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4905 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4906 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4907 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
4908 ASSERT_EQ(0, motionArgs.flags);
4909 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4910 ASSERT_EQ(0, motionArgs.buttonState);
4911 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004912 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004913 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004914 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004915 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4916 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4917 1, 0, 0, 0, 0, 0, 0, 0));
4918 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4919 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4920 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4921
4922 // Up.
4923 processUp(mapper);
4924 processSync(mapper);
4925
4926 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4927 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4928 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4929 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4930 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4931 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4932 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4933 ASSERT_EQ(0, motionArgs.flags);
4934 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4935 ASSERT_EQ(0, motionArgs.buttonState);
4936 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004937 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004938 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004939 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004940 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4941 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4942 1, 0, 0, 0, 0, 0, 0, 0));
4943 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4944 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4945 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4946
4947 // Should not have sent any more keys or motions.
4948 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4949 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4950}
4951
Michael Wrightd02c5b62014-02-10 15:10:22 -08004952TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004953 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004954 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004955 prepareButtons();
4956 prepareAxes(POSITION);
4957 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004958 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004959
arthurhungdcef2dc2020-08-11 14:47:50 +08004960 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004961
4962 NotifyMotionArgs motionArgs;
4963
4964 // Down.
4965 int32_t x = 100;
4966 int32_t y = 125;
4967 processDown(mapper, x, y);
4968 processSync(mapper);
4969
4970 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4971 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4972 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4973 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4974 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4975 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4976 ASSERT_EQ(0, motionArgs.flags);
4977 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4978 ASSERT_EQ(0, motionArgs.buttonState);
4979 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004980 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004981 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004982 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004983 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4984 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4985 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4986 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4987 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4988
4989 // Move.
4990 x += 50;
4991 y += 75;
4992 processMove(mapper, x, y);
4993 processSync(mapper);
4994
4995 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4996 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4997 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4998 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4999 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5000 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5001 ASSERT_EQ(0, motionArgs.flags);
5002 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5003 ASSERT_EQ(0, motionArgs.buttonState);
5004 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005005 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08005006 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005007 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005008 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5009 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
5010 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5011 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5012 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5013
5014 // Up.
5015 processUp(mapper);
5016 processSync(mapper);
5017
5018 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5019 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
5020 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
5021 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
5022 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
5023 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5024 ASSERT_EQ(0, motionArgs.flags);
5025 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
5026 ASSERT_EQ(0, motionArgs.buttonState);
5027 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07005028 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08005029 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005030 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005031 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5032 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
5033 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5034 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5035 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5036
5037 // Should not have sent any more keys or motions.
5038 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5039 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5040}
5041
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005042TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_DoesNotRotateMotions) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005043 addConfigurationProperty("touch.deviceType", "touchScreen");
5044 prepareButtons();
5045 prepareAxes(POSITION);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005046 // InputReader works in the un-rotated coordinate space, so orientation-aware devices do not
5047 // need to be rotated. Touchscreens are orientation-aware by default.
Arpit Singha8c236b2023-04-25 13:56:05 +00005048 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005049
5050 NotifyMotionArgs args;
5051
5052 // Rotation 90.
Michael Wrighta9cf4192022-12-01 23:46:39 +00005053 prepareDisplay(ui::ROTATION_90);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005054 processDown(mapper, toRawX(50), toRawY(75));
5055 processSync(mapper);
5056
5057 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5058 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5059 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5060
5061 processUp(mapper);
5062 processSync(mapper);
5063 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5064}
5065
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005066TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_RotatesMotions) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005067 addConfigurationProperty("touch.deviceType", "touchScreen");
5068 prepareButtons();
5069 prepareAxes(POSITION);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005070 // Since InputReader works in the un-rotated coordinate space, only devices that are not
5071 // orientation-aware are affected by display rotation.
5072 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00005073 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005074
5075 NotifyMotionArgs args;
5076
5077 // Rotation 0.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005078 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005079 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005080 processDown(mapper, toRawX(50), toRawY(75));
5081 processSync(mapper);
5082
5083 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5084 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5085 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5086
5087 processUp(mapper);
5088 processSync(mapper);
5089 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5090
5091 // Rotation 90.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005092 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005093 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005094 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005095 processSync(mapper);
5096
5097 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5098 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5099 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5100
5101 processUp(mapper);
5102 processSync(mapper);
5103 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5104
5105 // Rotation 180.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005106 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005107 prepareDisplay(ui::ROTATION_180);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005108 processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
5109 processSync(mapper);
5110
5111 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5112 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5113 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5114
5115 processUp(mapper);
5116 processSync(mapper);
5117 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5118
5119 // Rotation 270.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005120 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005121 prepareDisplay(ui::ROTATION_270);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005122 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005123 processSync(mapper);
5124
5125 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5126 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5127 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5128
5129 processUp(mapper);
5130 processSync(mapper);
5131 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5132}
5133
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005134TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation0_RotatesMotions) {
5135 addConfigurationProperty("touch.deviceType", "touchScreen");
5136 prepareButtons();
5137 prepareAxes(POSITION);
5138 addConfigurationProperty("touch.orientationAware", "1");
5139 addConfigurationProperty("touch.orientation", "ORIENTATION_0");
5140 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005141 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005142 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005143 NotifyMotionArgs args;
5144
5145 // Orientation 0.
5146 processDown(mapper, toRawX(50), toRawY(75));
5147 processSync(mapper);
5148
5149 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5150 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5151 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5152
5153 processUp(mapper);
5154 processSync(mapper);
5155 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5156}
5157
5158TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation90_RotatesMotions) {
5159 addConfigurationProperty("touch.deviceType", "touchScreen");
5160 prepareButtons();
5161 prepareAxes(POSITION);
5162 addConfigurationProperty("touch.orientationAware", "1");
5163 addConfigurationProperty("touch.orientation", "ORIENTATION_90");
5164 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005165 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005166 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005167 NotifyMotionArgs args;
5168
5169 // Orientation 90.
5170 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
5171 processSync(mapper);
5172
5173 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5174 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5175 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5176
5177 processUp(mapper);
5178 processSync(mapper);
5179 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5180}
5181
5182TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation180_RotatesMotions) {
5183 addConfigurationProperty("touch.deviceType", "touchScreen");
5184 prepareButtons();
5185 prepareAxes(POSITION);
5186 addConfigurationProperty("touch.orientationAware", "1");
5187 addConfigurationProperty("touch.orientation", "ORIENTATION_180");
5188 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005189 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005190 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005191 NotifyMotionArgs args;
5192
5193 // Orientation 180.
5194 processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
5195 processSync(mapper);
5196
5197 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5198 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5199 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5200
5201 processUp(mapper);
5202 processSync(mapper);
5203 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5204}
5205
5206TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation270_RotatesMotions) {
5207 addConfigurationProperty("touch.deviceType", "touchScreen");
5208 prepareButtons();
5209 prepareAxes(POSITION);
5210 addConfigurationProperty("touch.orientationAware", "1");
5211 addConfigurationProperty("touch.orientation", "ORIENTATION_270");
5212 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005213 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005214 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005215 NotifyMotionArgs args;
5216
5217 // Orientation 270.
5218 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
5219 processSync(mapper);
5220
5221 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5222 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5223 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5224
5225 processUp(mapper);
5226 processSync(mapper);
5227 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5228}
5229
5230TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationSpecified_RotatesMotionWithDisplay) {
5231 addConfigurationProperty("touch.deviceType", "touchScreen");
5232 prepareButtons();
5233 prepareAxes(POSITION);
5234 // Since InputReader works in the un-rotated coordinate space, only devices that are not
5235 // orientation-aware are affected by display rotation.
5236 addConfigurationProperty("touch.orientationAware", "0");
5237 addConfigurationProperty("touch.orientation", "ORIENTATION_90");
Arpit Singha8c236b2023-04-25 13:56:05 +00005238 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005239
5240 NotifyMotionArgs args;
5241
5242 // Orientation 90, Rotation 0.
5243 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005244 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005245 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
5246 processSync(mapper);
5247
5248 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5249 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5250 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5251
5252 processUp(mapper);
5253 processSync(mapper);
5254 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5255
5256 // Orientation 90, Rotation 90.
5257 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005258 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005259 processDown(mapper, toRawX(50), toRawY(75));
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005260 processSync(mapper);
5261
5262 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5263 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5264 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5265
5266 processUp(mapper);
5267 processSync(mapper);
5268 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5269
5270 // Orientation 90, Rotation 180.
5271 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005272 prepareDisplay(ui::ROTATION_180);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005273 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
5274 processSync(mapper);
5275
5276 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5277 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5278 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5279
5280 processUp(mapper);
5281 processSync(mapper);
5282 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5283
5284 // Orientation 90, Rotation 270.
5285 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005286 prepareDisplay(ui::ROTATION_270);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005287 processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005288 processSync(mapper);
5289
5290 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5291 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5292 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5293
5294 processUp(mapper);
5295 processSync(mapper);
5296 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5297}
5298
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005299TEST_F(SingleTouchInputMapperTest, Process_IgnoresTouchesOutsidePhysicalFrame) {
5300 addConfigurationProperty("touch.deviceType", "touchScreen");
5301 prepareButtons();
5302 prepareAxes(POSITION);
5303 addConfigurationProperty("touch.orientationAware", "1");
5304 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005305 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005306
5307 // Set a physical frame in the display viewport.
5308 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
5309 viewport->physicalLeft = 20;
5310 viewport->physicalTop = 600;
5311 viewport->physicalRight = 30;
5312 viewport->physicalBottom = 610;
5313 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00005314 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005315
5316 // Start the touch.
5317 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
5318 processSync(mapper);
5319
5320 // Expect all input starting outside the physical frame to be ignored.
5321 const std::array<Point, 6> outsidePoints = {
5322 {{0, 0}, {19, 605}, {31, 605}, {25, 599}, {25, 611}, {DISPLAY_WIDTH, DISPLAY_HEIGHT}}};
5323 for (const auto& p : outsidePoints) {
5324 processMove(mapper, toRawX(p.x), toRawY(p.y));
5325 processSync(mapper);
5326 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5327 }
5328
5329 // Move the touch into the physical frame.
5330 processMove(mapper, toRawX(25), toRawY(605));
5331 processSync(mapper);
5332 NotifyMotionArgs args;
5333 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5334 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
5335 EXPECT_NEAR(25, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5336 EXPECT_NEAR(605, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5337
5338 // Once the touch down is reported, continue reporting input, even if it is outside the frame.
5339 for (const auto& p : outsidePoints) {
5340 processMove(mapper, toRawX(p.x), toRawY(p.y));
5341 processSync(mapper);
5342 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5343 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
5344 EXPECT_NEAR(p.x, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5345 EXPECT_NEAR(p.y, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5346 }
5347
5348 processUp(mapper);
5349 processSync(mapper);
5350 EXPECT_NO_FATAL_FAILURE(
5351 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
5352}
5353
Harry Cutts1db43992023-06-19 17:05:07 +00005354TEST_F(SingleTouchInputMapperTest, Process_DoesntCheckPhysicalFrameForTouchpads) {
Harry Cutts1db43992023-06-19 17:05:07 +00005355 addConfigurationProperty("touch.deviceType", "pointer");
5356 prepareAxes(POSITION);
5357 prepareDisplay(ui::ROTATION_0);
5358 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
5359
5360 // Set a physical frame in the display viewport.
5361 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
5362 viewport->physicalLeft = 20;
5363 viewport->physicalTop = 600;
5364 viewport->physicalRight = 30;
5365 viewport->physicalBottom = 610;
5366 mFakePolicy->updateViewport(*viewport);
5367 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
5368
5369 // Start the touch.
5370 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
5371 processSync(mapper);
5372
5373 // Expect all input starting outside the physical frame to result in NotifyMotionArgs being
5374 // produced.
5375 const std::array<Point, 6> outsidePoints = {
5376 {{0, 0}, {19, 605}, {31, 605}, {25, 599}, {25, 611}, {DISPLAY_WIDTH, DISPLAY_HEIGHT}}};
5377 for (const auto& p : outsidePoints) {
5378 processMove(mapper, toRawX(p.x), toRawY(p.y));
5379 processSync(mapper);
5380 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5381 }
5382}
5383
Michael Wrightd02c5b62014-02-10 15:10:22 -08005384TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005385 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005386 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005387 prepareButtons();
5388 prepareAxes(POSITION | PRESSURE | TOOL | DISTANCE | TILT);
Arpit Singha8c236b2023-04-25 13:56:05 +00005389 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005390
5391 // These calculations are based on the input device calibration documentation.
5392 int32_t rawX = 100;
5393 int32_t rawY = 200;
5394 int32_t rawPressure = 10;
5395 int32_t rawToolMajor = 12;
5396 int32_t rawDistance = 2;
5397 int32_t rawTiltX = 30;
5398 int32_t rawTiltY = 110;
5399
5400 float x = toDisplayX(rawX);
5401 float y = toDisplayY(rawY);
5402 float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
5403 float size = float(rawToolMajor) / RAW_TOOL_MAX;
5404 float tool = float(rawToolMajor) * GEOMETRIC_SCALE;
5405 float distance = float(rawDistance);
5406
5407 float tiltCenter = (RAW_TILT_MAX + RAW_TILT_MIN) * 0.5f;
5408 float tiltScale = M_PI / 180;
5409 float tiltXAngle = (rawTiltX - tiltCenter) * tiltScale;
5410 float tiltYAngle = (rawTiltY - tiltCenter) * tiltScale;
5411 float orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
5412 float tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
5413
5414 processDown(mapper, rawX, rawY);
5415 processPressure(mapper, rawPressure);
5416 processToolMajor(mapper, rawToolMajor);
5417 processDistance(mapper, rawDistance);
5418 processTilt(mapper, rawTiltX, rawTiltY);
5419 processSync(mapper);
5420
5421 NotifyMotionArgs args;
5422 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5423 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
5424 x, y, pressure, size, tool, tool, tool, tool, orientation, distance));
5425 ASSERT_EQ(tilt, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TILT));
Prabir Pradhan9a53b552024-06-04 02:59:40 +00005426 ASSERT_EQ(args.flags,
5427 AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION |
5428 AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005429}
5430
Jason Gerecke489fda82012-09-07 17:19:40 -07005431TEST_F(SingleTouchInputMapperTest, Process_XYAxes_AffineCalibration) {
Jason Gerecke489fda82012-09-07 17:19:40 -07005432 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005433 prepareDisplay(ui::ROTATION_0);
Jason Gerecke489fda82012-09-07 17:19:40 -07005434 prepareLocationCalibration();
5435 prepareButtons();
5436 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005437 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Jason Gerecke489fda82012-09-07 17:19:40 -07005438
5439 int32_t rawX = 100;
5440 int32_t rawY = 200;
5441
5442 float x = toDisplayX(toCookedX(rawX, rawY));
5443 float y = toDisplayY(toCookedY(rawX, rawY));
5444
5445 processDown(mapper, rawX, rawY);
5446 processSync(mapper);
5447
5448 NotifyMotionArgs args;
5449 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5450 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
5451 x, y, 1, 0, 0, 0, 0, 0, 0, 0));
5452}
5453
Michael Wrightd02c5b62014-02-10 15:10:22 -08005454TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllButtons) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005455 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005456 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005457 prepareButtons();
5458 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005459 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005460
5461 NotifyMotionArgs motionArgs;
5462 NotifyKeyArgs keyArgs;
5463
5464 processDown(mapper, 100, 200);
5465 processSync(mapper);
5466 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5467 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5468 ASSERT_EQ(0, motionArgs.buttonState);
5469
5470 // press BTN_LEFT, release BTN_LEFT
5471 processKey(mapper, BTN_LEFT, 1);
5472 processSync(mapper);
5473 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5474 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5475 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
5476
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005477 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5478 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5479 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
5480
Michael Wrightd02c5b62014-02-10 15:10:22 -08005481 processKey(mapper, BTN_LEFT, 0);
5482 processSync(mapper);
5483 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005484 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005485 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005486
5487 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005488 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005489 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005490
5491 // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
5492 processKey(mapper, BTN_RIGHT, 1);
5493 processKey(mapper, BTN_MIDDLE, 1);
5494 processSync(mapper);
5495 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5496 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5497 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
5498 motionArgs.buttonState);
5499
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005500 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5501 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5502 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
5503
5504 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5505 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5506 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
5507 motionArgs.buttonState);
5508
Michael Wrightd02c5b62014-02-10 15:10:22 -08005509 processKey(mapper, BTN_RIGHT, 0);
5510 processSync(mapper);
5511 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005512 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005513 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005514
5515 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005516 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005517 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005518
5519 processKey(mapper, BTN_MIDDLE, 0);
5520 processSync(mapper);
5521 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005522 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005523 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005524
5525 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005526 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005527 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005528
5529 // press BTN_BACK, release BTN_BACK
5530 processKey(mapper, BTN_BACK, 1);
5531 processSync(mapper);
5532 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5533 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5534 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005535
Michael Wrightd02c5b62014-02-10 15:10:22 -08005536 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005537 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005538 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
5539
5540 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5541 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5542 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005543
5544 processKey(mapper, BTN_BACK, 0);
5545 processSync(mapper);
5546 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005547 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005548 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005549
5550 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005551 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005552 ASSERT_EQ(0, motionArgs.buttonState);
5553
Michael Wrightd02c5b62014-02-10 15:10:22 -08005554 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5555 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5556 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
5557
5558 // press BTN_SIDE, release BTN_SIDE
5559 processKey(mapper, BTN_SIDE, 1);
5560 processSync(mapper);
5561 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5562 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5563 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005564
Michael Wrightd02c5b62014-02-10 15:10:22 -08005565 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005566 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005567 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
5568
5569 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5570 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5571 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005572
5573 processKey(mapper, BTN_SIDE, 0);
5574 processSync(mapper);
5575 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005576 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005577 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005578
5579 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005580 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005581 ASSERT_EQ(0, motionArgs.buttonState);
5582
Michael Wrightd02c5b62014-02-10 15:10:22 -08005583 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5584 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5585 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
5586
5587 // press BTN_FORWARD, release BTN_FORWARD
5588 processKey(mapper, BTN_FORWARD, 1);
5589 processSync(mapper);
5590 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5591 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5592 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005593
Michael Wrightd02c5b62014-02-10 15:10:22 -08005594 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005595 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005596 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
5597
5598 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5599 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5600 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005601
5602 processKey(mapper, BTN_FORWARD, 0);
5603 processSync(mapper);
5604 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005605 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005606 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005607
5608 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005609 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005610 ASSERT_EQ(0, motionArgs.buttonState);
5611
Michael Wrightd02c5b62014-02-10 15:10:22 -08005612 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5613 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5614 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
5615
5616 // press BTN_EXTRA, release BTN_EXTRA
5617 processKey(mapper, BTN_EXTRA, 1);
5618 processSync(mapper);
5619 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5620 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5621 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005622
Michael Wrightd02c5b62014-02-10 15:10:22 -08005623 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005624 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005625 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
5626
5627 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5628 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5629 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005630
5631 processKey(mapper, BTN_EXTRA, 0);
5632 processSync(mapper);
5633 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005634 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005635 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005636
5637 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005638 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005639 ASSERT_EQ(0, motionArgs.buttonState);
5640
Michael Wrightd02c5b62014-02-10 15:10:22 -08005641 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5642 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5643 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
5644
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005645 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5646
Michael Wrightd02c5b62014-02-10 15:10:22 -08005647 // press BTN_STYLUS, release BTN_STYLUS
5648 processKey(mapper, BTN_STYLUS, 1);
5649 processSync(mapper);
5650 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5651 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005652 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
5653
5654 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5655 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5656 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005657
5658 processKey(mapper, BTN_STYLUS, 0);
5659 processSync(mapper);
5660 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005661 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005662 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005663
5664 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005665 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005666 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005667
5668 // press BTN_STYLUS2, release BTN_STYLUS2
5669 processKey(mapper, BTN_STYLUS2, 1);
5670 processSync(mapper);
5671 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5672 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005673 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
5674
5675 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5676 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5677 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005678
5679 processKey(mapper, BTN_STYLUS2, 0);
5680 processSync(mapper);
5681 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005682 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005683 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005684
5685 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005686 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005687 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005688
5689 // release touch
5690 processUp(mapper);
5691 processSync(mapper);
5692 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5693 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5694 ASSERT_EQ(0, motionArgs.buttonState);
5695}
5696
5697TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005698 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005699 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005700 prepareButtons();
5701 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005702 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005703
5704 NotifyMotionArgs motionArgs;
5705
5706 // default tool type is finger
5707 processDown(mapper, 100, 200);
5708 processSync(mapper);
5709 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5710 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005711 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005712
5713 // eraser
5714 processKey(mapper, BTN_TOOL_RUBBER, 1);
5715 processSync(mapper);
5716 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5717 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005718 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005719
5720 // stylus
5721 processKey(mapper, BTN_TOOL_RUBBER, 0);
5722 processKey(mapper, BTN_TOOL_PEN, 1);
5723 processSync(mapper);
5724 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5725 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005726 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005727
5728 // brush
5729 processKey(mapper, BTN_TOOL_PEN, 0);
5730 processKey(mapper, BTN_TOOL_BRUSH, 1);
5731 processSync(mapper);
5732 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5733 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005734 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005735
5736 // pencil
5737 processKey(mapper, BTN_TOOL_BRUSH, 0);
5738 processKey(mapper, BTN_TOOL_PENCIL, 1);
5739 processSync(mapper);
5740 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5741 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005742 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005743
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08005744 // air-brush
Michael Wrightd02c5b62014-02-10 15:10:22 -08005745 processKey(mapper, BTN_TOOL_PENCIL, 0);
5746 processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
5747 processSync(mapper);
5748 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5749 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005750 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005751
5752 // mouse
5753 processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
5754 processKey(mapper, BTN_TOOL_MOUSE, 1);
5755 processSync(mapper);
5756 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5757 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005758 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005759
5760 // lens
5761 processKey(mapper, BTN_TOOL_MOUSE, 0);
5762 processKey(mapper, BTN_TOOL_LENS, 1);
5763 processSync(mapper);
5764 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5765 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005766 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005767
5768 // double-tap
5769 processKey(mapper, BTN_TOOL_LENS, 0);
5770 processKey(mapper, BTN_TOOL_DOUBLETAP, 1);
5771 processSync(mapper);
5772 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5773 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005774 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005775
5776 // triple-tap
5777 processKey(mapper, BTN_TOOL_DOUBLETAP, 0);
5778 processKey(mapper, BTN_TOOL_TRIPLETAP, 1);
5779 processSync(mapper);
5780 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5781 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005782 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005783
5784 // quad-tap
5785 processKey(mapper, BTN_TOOL_TRIPLETAP, 0);
5786 processKey(mapper, BTN_TOOL_QUADTAP, 1);
5787 processSync(mapper);
5788 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5789 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005790 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005791
5792 // finger
5793 processKey(mapper, BTN_TOOL_QUADTAP, 0);
5794 processKey(mapper, BTN_TOOL_FINGER, 1);
5795 processSync(mapper);
5796 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5797 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005798 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005799
5800 // stylus trumps finger
5801 processKey(mapper, BTN_TOOL_PEN, 1);
5802 processSync(mapper);
5803 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5804 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005805 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005806
5807 // eraser trumps stylus
5808 processKey(mapper, BTN_TOOL_RUBBER, 1);
5809 processSync(mapper);
5810 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5811 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005812 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005813
5814 // mouse trumps eraser
5815 processKey(mapper, BTN_TOOL_MOUSE, 1);
5816 processSync(mapper);
5817 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5818 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005819 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005820
5821 // back to default tool type
5822 processKey(mapper, BTN_TOOL_MOUSE, 0);
5823 processKey(mapper, BTN_TOOL_RUBBER, 0);
5824 processKey(mapper, BTN_TOOL_PEN, 0);
5825 processKey(mapper, BTN_TOOL_FINGER, 0);
5826 processSync(mapper);
5827 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5828 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005829 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005830}
5831
5832TEST_F(SingleTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005833 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005834 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005835 prepareButtons();
5836 prepareAxes(POSITION);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08005837 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_FINGER, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005838 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005839
5840 NotifyMotionArgs motionArgs;
5841
5842 // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0
5843 processKey(mapper, BTN_TOOL_FINGER, 1);
5844 processMove(mapper, 100, 200);
5845 processSync(mapper);
5846 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5847 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5848 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5849 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5850
5851 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5852 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5853 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5854 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5855
5856 // move a little
5857 processMove(mapper, 150, 250);
5858 processSync(mapper);
5859 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5860 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5861 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5862 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5863
5864 // down when BTN_TOUCH is pressed, pressure defaults to 1
5865 processKey(mapper, BTN_TOUCH, 1);
5866 processSync(mapper);
5867 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5868 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5869 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5870 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5871
5872 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5873 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5874 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5875 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5876
5877 // up when BTN_TOUCH is released, hover restored
5878 processKey(mapper, BTN_TOUCH, 0);
5879 processSync(mapper);
5880 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5881 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5882 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5883 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5884
5885 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5886 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5887 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5888 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5889
5890 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5891 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5892 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5893 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5894
5895 // exit hover when pointer goes away
5896 processKey(mapper, BTN_TOOL_FINGER, 0);
5897 processSync(mapper);
5898 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5899 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5900 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5901 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5902}
5903
5904TEST_F(SingleTouchInputMapperTest, Process_WhenAbsPressureIsPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005905 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005906 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005907 prepareButtons();
5908 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00005909 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005910
5911 NotifyMotionArgs motionArgs;
5912
5913 // initially hovering because pressure is 0
5914 processDown(mapper, 100, 200);
5915 processPressure(mapper, 0);
5916 processSync(mapper);
5917 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5918 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5919 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5920 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5921
5922 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5923 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5924 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5925 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5926
5927 // move a little
5928 processMove(mapper, 150, 250);
5929 processSync(mapper);
5930 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5931 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5932 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5933 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5934
5935 // down when pressure is non-zero
5936 processPressure(mapper, RAW_PRESSURE_MAX);
5937 processSync(mapper);
5938 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5939 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5940 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5941 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5942
5943 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5944 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5945 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5946 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5947
5948 // up when pressure becomes 0, hover restored
5949 processPressure(mapper, 0);
5950 processSync(mapper);
5951 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5952 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5953 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5954 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5955
5956 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5957 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5958 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5959 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5960
5961 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5962 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5963 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5964 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5965
5966 // exit hover when pointer goes away
5967 processUp(mapper);
5968 processSync(mapper);
5969 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5970 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5971 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5972 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5973}
5974
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00005975TEST_F(SingleTouchInputMapperTest, Reset_CancelsOngoingGesture) {
5976 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005977 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00005978 prepareButtons();
5979 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00005980 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00005981
5982 // Touch down.
5983 processDown(mapper, 100, 200);
5984 processPressure(mapper, 1);
5985 processSync(mapper);
5986 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
5987 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
5988
5989 // Reset the mapper. This should cancel the ongoing gesture.
5990 resetMapper(mapper, ARBITRARY_TIME);
5991 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
5992 WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
5993
5994 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5995}
5996
Prabir Pradhanafabcde2022-09-27 19:32:43 +00005997TEST_F(SingleTouchInputMapperTest, Reset_RecreatesTouchState) {
5998 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005999 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006000 prepareButtons();
6001 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00006002 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006003
6004 // Set the initial state for the touch pointer.
6005 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_X, 100);
6006 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_Y, 200);
6007 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_PRESSURE, RAW_PRESSURE_MAX);
6008 mFakeEventHub->setScanCodeState(EVENTHUB_ID, BTN_TOUCH, 1);
6009
6010 // Reset the mapper. When the mapper is reset, we expect it to attempt to recreate the touch
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00006011 // state by reading the current axis values. Since there was no ongoing gesture, calling reset
6012 // does not generate any events.
6013 resetMapper(mapper, ARBITRARY_TIME);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006014
6015 // Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
6016 // the recreated touch state to generate a down event.
6017 processSync(mapper);
6018 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6019 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPressure(1.f))));
6020
6021 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6022}
6023
lilinnan687e58f2022-07-19 16:00:50 +08006024TEST_F(SingleTouchInputMapperTest,
6025 Process_WhenViewportDisplayIdChanged_TouchIsCanceledAndDeviceIsReset) {
6026 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006027 prepareDisplay(ui::ROTATION_0);
lilinnan687e58f2022-07-19 16:00:50 +08006028 prepareButtons();
6029 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006030 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
lilinnan687e58f2022-07-19 16:00:50 +08006031 NotifyMotionArgs motionArgs;
6032
6033 // Down.
Prabir Pradhan3e5ec702022-07-29 16:26:24 +00006034 processDown(mapper, 100, 200);
lilinnan687e58f2022-07-19 16:00:50 +08006035 processSync(mapper);
6036
6037 // We should receive a down event
6038 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6039 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6040
6041 // Change display id
6042 clearViewports();
6043 prepareSecondaryDisplay(ViewportType::INTERNAL);
6044
6045 // We should receive a cancel event
6046 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6047 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
6048 // Then receive reset called
6049 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6050}
6051
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006052TEST_F(SingleTouchInputMapperTest,
6053 Process_WhenViewportActiveStatusChanged_TouchIsCanceledAndDeviceIsReset) {
6054 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006055 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006056 prepareButtons();
6057 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006058 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006059 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6060 NotifyMotionArgs motionArgs;
6061
6062 // Start a new gesture.
6063 processDown(mapper, 100, 200);
6064 processSync(mapper);
6065 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6066 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6067
6068 // Make the viewport inactive. This will put the device in disabled mode.
6069 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6070 viewport->isActive = false;
6071 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006072 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006073
6074 // We should receive a cancel event for the ongoing gesture.
6075 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6076 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
6077 // Then we should be notified that the device was reset.
6078 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6079
6080 // No events are generated while the viewport is inactive.
6081 processMove(mapper, 101, 201);
6082 processSync(mapper);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006083 processUp(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006084 processSync(mapper);
6085 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6086
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006087 // Start a new gesture while the viewport is still inactive.
6088 processDown(mapper, 300, 400);
6089 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_X, 300);
6090 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_Y, 400);
6091 mFakeEventHub->setScanCodeState(EVENTHUB_ID, BTN_TOUCH, 1);
6092 processSync(mapper);
6093
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006094 // Make the viewport active again. The device should resume processing events.
6095 viewport->isActive = true;
6096 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006097 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006098
6099 // The device is reset because it changes back to direct mode, without generating any events.
6100 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6101 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6102
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006103 // In the next sync, the touch state that was recreated when the device was reset is reported.
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006104 processSync(mapper);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006105 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6106 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006107
6108 // No more events.
6109 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6110 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
6111}
6112
Prabir Pradhan211ba622022-10-31 21:09:21 +00006113TEST_F(SingleTouchInputMapperTest, ButtonIsReleasedOnTouchUp) {
6114 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006115 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan211ba622022-10-31 21:09:21 +00006116 prepareButtons();
6117 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006118 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan211ba622022-10-31 21:09:21 +00006119 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6120
6121 // Press a stylus button.
6122 processKey(mapper, BTN_STYLUS, 1);
6123 processSync(mapper);
6124
6125 // Start a touch gesture and ensure the BUTTON_PRESS event is generated.
6126 processDown(mapper, 100, 200);
6127 processSync(mapper);
6128 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6129 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6130 WithCoords(toDisplayX(100), toDisplayY(200)),
6131 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6132 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6133 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
6134 WithCoords(toDisplayX(100), toDisplayY(200)),
6135 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6136
6137 // Release the touch gesture. Ensure that the BUTTON_RELEASE event is generated even though
6138 // the button has not actually been released, since there will be no pointers through which the
6139 // button state can be reported. The event is generated at the location of the pointer before
6140 // it went up.
6141 processUp(mapper);
6142 processSync(mapper);
6143 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6144 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
6145 WithCoords(toDisplayX(100), toDisplayY(200)), WithButtonState(0))));
6146 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6147 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6148 WithCoords(toDisplayX(100), toDisplayY(200)), WithButtonState(0))));
6149}
6150
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00006151TEST_F(SingleTouchInputMapperTest, StylusButtonMotionEventsDisabled) {
6152 addConfigurationProperty("touch.deviceType", "touchScreen");
6153 prepareDisplay(ui::ROTATION_0);
6154 prepareButtons();
6155 prepareAxes(POSITION);
6156
6157 mFakePolicy->setStylusButtonMotionEventsEnabled(false);
6158
Arpit Singha8c236b2023-04-25 13:56:05 +00006159 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00006160 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6161
6162 // Press a stylus button.
6163 processKey(mapper, BTN_STYLUS, 1);
6164 processSync(mapper);
6165
6166 // Start a touch gesture and ensure that the stylus button is not reported.
6167 processDown(mapper, 100, 200);
6168 processSync(mapper);
6169 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6170 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithButtonState(0))));
6171
6172 // Release and press the stylus button again.
6173 processKey(mapper, BTN_STYLUS, 0);
6174 processSync(mapper);
6175 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6176 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
6177 processKey(mapper, BTN_STYLUS, 1);
6178 processSync(mapper);
6179 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6180 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
6181
6182 // Release the touch gesture.
6183 processUp(mapper);
6184 processSync(mapper);
6185 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6186 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
6187
6188 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6189}
6190
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006191TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsSetToTouchNavigation_setsCorrectType) {
6192 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
6193 prepareDisplay(ui::ROTATION_0);
6194 prepareButtons();
6195 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006196 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006197 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6198
Prabir Pradhan9cf8f322024-06-18 20:22:42 +00006199 ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION | AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006200}
6201
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006202TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsChangedToTouchNavigation_updatesDeviceType) {
6203 // Initialize the device without setting device source to touch navigation.
6204 addConfigurationProperty("touch.deviceType", "touchScreen");
6205 prepareDisplay(ui::ROTATION_0);
6206 prepareButtons();
6207 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006208 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006209
6210 // Ensure that the device is created as a touchscreen, not touch navigation.
6211 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
6212
6213 // Add device type association after the device was created.
6214 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
6215
6216 // Send update to the mapper.
6217 std::list<NotifyArgs> unused2 =
6218 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006219 InputReaderConfiguration::Change::DEVICE_TYPE /*changes*/);
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006220
6221 // Check whether device type update was successful.
Prabir Pradhan9cf8f322024-06-18 20:22:42 +00006222 ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION | AINPUT_SOURCE_TOUCHPAD, mDevice->getSources());
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006223}
6224
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006225TEST_F(SingleTouchInputMapperTest, HoverEventsOutsidePhysicalFrameAreIgnored) {
6226 // Initialize the device without setting device source to touch navigation.
6227 addConfigurationProperty("touch.deviceType", "touchScreen");
6228 prepareDisplay(ui::ROTATION_0);
6229 prepareButtons();
6230 prepareAxes(POSITION);
6231 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
6232
6233 // Set a physical frame in the display viewport.
6234 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6235 viewport->physicalLeft = 0;
6236 viewport->physicalTop = 0;
6237 viewport->physicalRight = DISPLAY_WIDTH / 2;
6238 viewport->physicalBottom = DISPLAY_HEIGHT / 2;
6239 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006240 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006241
Arpit Singha8c236b2023-04-25 13:56:05 +00006242 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006243
6244 // Hovering inside the physical frame produces events.
6245 processKey(mapper, BTN_TOOL_PEN, 1);
6246 processMove(mapper, RAW_X_MIN + 1, RAW_Y_MIN + 1);
6247 processSync(mapper);
6248 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6249 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)));
6250 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6251 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)));
6252
6253 // Leaving the physical frame ends the hovering gesture.
6254 processMove(mapper, RAW_X_MAX - 1, RAW_Y_MAX - 1);
6255 processSync(mapper);
6256 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6257 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT)));
6258
6259 // Moving outside the physical frame does not produce events.
6260 processMove(mapper, RAW_X_MAX - 2, RAW_Y_MAX - 2);
6261 processSync(mapper);
6262 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6263
6264 // Re-entering the physical frame produces events.
6265 processMove(mapper, RAW_X_MIN, RAW_Y_MIN);
6266 processSync(mapper);
6267 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6268 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)));
6269 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6270 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)));
6271}
6272
Prabir Pradhan5632d622021-09-06 07:57:20 -07006273// --- TouchDisplayProjectionTest ---
6274
6275class TouchDisplayProjectionTest : public SingleTouchInputMapperTest {
6276public:
6277 // The values inside DisplayViewport are expected to be pre-rotated. This updates the current
6278 // DisplayViewport to pre-rotate the values. The viewport's physical display will be set to the
6279 // rotated equivalent of the given un-rotated physical display bounds.
Prabir Pradhana9df3162022-12-05 23:57:27 +00006280 void configurePhysicalDisplay(ui::Rotation orientation, Rect naturalPhysicalDisplay,
6281 int32_t naturalDisplayWidth = DISPLAY_WIDTH,
6282 int32_t naturalDisplayHeight = DISPLAY_HEIGHT) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006283 uint32_t inverseRotationFlags;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006284 auto rotatedWidth = naturalDisplayWidth;
6285 auto rotatedHeight = naturalDisplayHeight;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006286 switch (orientation) {
Michael Wrighta9cf4192022-12-01 23:46:39 +00006287 case ui::ROTATION_90:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006288 inverseRotationFlags = ui::Transform::ROT_270;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006289 std::swap(rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006290 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006291 case ui::ROTATION_180:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006292 inverseRotationFlags = ui::Transform::ROT_180;
6293 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006294 case ui::ROTATION_270:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006295 inverseRotationFlags = ui::Transform::ROT_90;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006296 std::swap(rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006297 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006298 case ui::ROTATION_0:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006299 inverseRotationFlags = ui::Transform::ROT_0;
6300 break;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006301 }
6302
Prabir Pradhana9df3162022-12-05 23:57:27 +00006303 const ui::Transform rotation(inverseRotationFlags, rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006304 const Rect rotatedPhysicalDisplay = rotation.transform(naturalPhysicalDisplay);
6305
6306 std::optional<DisplayViewport> internalViewport =
6307 *mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6308 DisplayViewport& v = *internalViewport;
6309 v.displayId = DISPLAY_ID;
6310 v.orientation = orientation;
6311
6312 v.logicalLeft = 0;
6313 v.logicalTop = 0;
6314 v.logicalRight = 100;
6315 v.logicalBottom = 100;
6316
6317 v.physicalLeft = rotatedPhysicalDisplay.left;
6318 v.physicalTop = rotatedPhysicalDisplay.top;
6319 v.physicalRight = rotatedPhysicalDisplay.right;
6320 v.physicalBottom = rotatedPhysicalDisplay.bottom;
6321
Prabir Pradhana9df3162022-12-05 23:57:27 +00006322 v.deviceWidth = rotatedWidth;
6323 v.deviceHeight = rotatedHeight;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006324
6325 v.isActive = true;
6326 v.uniqueId = UNIQUE_ID;
6327 v.type = ViewportType::INTERNAL;
6328 mFakePolicy->updateViewport(v);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006329 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006330 }
6331
6332 void assertReceivedMove(const Point& point) {
6333 NotifyMotionArgs motionArgs;
6334 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6335 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006336 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Prabir Pradhan5632d622021-09-06 07:57:20 -07006337 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], point.x, point.y,
6338 1, 0, 0, 0, 0, 0, 0, 0));
6339 }
6340};
6341
6342TEST_F(TouchDisplayProjectionTest, IgnoresTouchesOutsidePhysicalDisplay) {
6343 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006344 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006345
6346 prepareButtons();
6347 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006348 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan5632d622021-09-06 07:57:20 -07006349
6350 NotifyMotionArgs motionArgs;
6351
6352 // Configure the DisplayViewport such that the logical display maps to a subsection of
6353 // the display panel called the physical display. Here, the physical display is bounded by the
6354 // points (10, 20) and (70, 160) inside the display space, which is of the size 400 x 800.
6355 static const Rect kPhysicalDisplay{10, 20, 70, 160};
6356 static const std::array<Point, 6> kPointsOutsidePhysicalDisplay{
6357 {{-10, -10}, {0, 0}, {5, 100}, {50, 15}, {75, 100}, {50, 165}}};
6358
Michael Wrighta9cf4192022-12-01 23:46:39 +00006359 for (auto orientation : {ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180, ui::ROTATION_270}) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006360 configurePhysicalDisplay(orientation, kPhysicalDisplay);
6361
6362 // Touches outside the physical display should be ignored, and should not generate any
6363 // events. Ensure touches at the following points that lie outside of the physical display
6364 // area do not generate any events.
6365 for (const auto& point : kPointsOutsidePhysicalDisplay) {
6366 processDown(mapper, toRawX(point.x), toRawY(point.y));
6367 processSync(mapper);
6368 processUp(mapper);
6369 processSync(mapper);
6370 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled())
6371 << "Unexpected event generated for touch outside physical display at point: "
6372 << point.x << ", " << point.y;
6373 }
6374 }
6375}
6376
6377TEST_F(TouchDisplayProjectionTest, EmitsTouchDownAfterEnteringPhysicalDisplay) {
6378 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006379 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006380
6381 prepareButtons();
6382 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006383 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan5632d622021-09-06 07:57:20 -07006384
6385 NotifyMotionArgs motionArgs;
6386
6387 // Configure the DisplayViewport such that the logical display maps to a subsection of
6388 // the display panel called the physical display. Here, the physical display is bounded by the
6389 // points (10, 20) and (70, 160) inside the display space, which is of the size 400 x 800.
6390 static const Rect kPhysicalDisplay{10, 20, 70, 160};
6391
Michael Wrighta9cf4192022-12-01 23:46:39 +00006392 for (auto orientation : {ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180, ui::ROTATION_270}) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006393 configurePhysicalDisplay(orientation, kPhysicalDisplay);
6394
6395 // Touches that start outside the physical display should be ignored until it enters the
6396 // physical display bounds, at which point it should generate a down event. Start a touch at
6397 // the point (5, 100), which is outside the physical display bounds.
6398 static const Point kOutsidePoint{5, 100};
6399 processDown(mapper, toRawX(kOutsidePoint.x), toRawY(kOutsidePoint.y));
6400 processSync(mapper);
6401 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6402
6403 // Move the touch into the physical display area. This should generate a pointer down.
6404 processMove(mapper, toRawX(11), toRawY(21));
6405 processSync(mapper);
6406 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6407 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006408 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Prabir Pradhan5632d622021-09-06 07:57:20 -07006409 ASSERT_NO_FATAL_FAILURE(
6410 assertPointerCoords(motionArgs.pointerCoords[0], 11, 21, 1, 0, 0, 0, 0, 0, 0, 0));
6411
6412 // Move the touch inside the physical display area. This should generate a pointer move.
6413 processMove(mapper, toRawX(69), toRawY(159));
6414 processSync(mapper);
6415 assertReceivedMove({69, 159});
6416
6417 // Move outside the physical display area. Since the pointer is already down, this should
6418 // now continue generating events.
6419 processMove(mapper, toRawX(kOutsidePoint.x), toRawY(kOutsidePoint.y));
6420 processSync(mapper);
6421 assertReceivedMove(kOutsidePoint);
6422
6423 // Release. This should generate a pointer up.
6424 processUp(mapper);
6425 processSync(mapper);
6426 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6427 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
6428 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], kOutsidePoint.x,
6429 kOutsidePoint.y, 1, 0, 0, 0, 0, 0, 0, 0));
6430
6431 // Ensure no more events were generated.
6432 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
6433 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6434 }
6435}
6436
Prabir Pradhana9df3162022-12-05 23:57:27 +00006437// --- TouchscreenPrecisionTests ---
6438
6439// This test suite is used to ensure that touchscreen devices are scaled and configured correctly
6440// in various orientations and with different display rotations. We configure the touchscreen to
6441// have a higher resolution than that of the display by an integer scale factor in each axis so that
6442// we can enforce that coordinates match precisely as expected.
6443class TouchscreenPrecisionTestsFixture : public TouchDisplayProjectionTest,
6444 public ::testing::WithParamInterface<ui::Rotation> {
6445public:
6446 void SetUp() override {
6447 SingleTouchInputMapperTest::SetUp();
6448
6449 // Prepare the raw axes to have twice the resolution of the display in the X axis and
6450 // four times the resolution of the display in the Y axis.
6451 prepareButtons();
6452 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, PRECISION_RAW_X_MIN, PRECISION_RAW_X_MAX,
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006453 PRECISION_RAW_X_FLAT, PRECISION_RAW_X_FUZZ,
6454 PRECISION_RAW_X_RES);
Prabir Pradhana9df3162022-12-05 23:57:27 +00006455 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, PRECISION_RAW_Y_MIN, PRECISION_RAW_Y_MAX,
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006456 PRECISION_RAW_Y_FLAT, PRECISION_RAW_Y_FUZZ,
6457 PRECISION_RAW_Y_RES);
Prabir Pradhana9df3162022-12-05 23:57:27 +00006458 }
6459
6460 static const int32_t PRECISION_RAW_X_MIN = TouchInputMapperTest::RAW_X_MIN;
6461 static const int32_t PRECISION_RAW_X_MAX = PRECISION_RAW_X_MIN + DISPLAY_WIDTH * 2 - 1;
6462 static const int32_t PRECISION_RAW_Y_MIN = TouchInputMapperTest::RAW_Y_MIN;
6463 static const int32_t PRECISION_RAW_Y_MAX = PRECISION_RAW_Y_MIN + DISPLAY_HEIGHT * 4 - 1;
6464
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006465 static const int32_t PRECISION_RAW_X_RES = 50; // units per millimeter
6466 static const int32_t PRECISION_RAW_Y_RES = 100; // units per millimeter
6467
6468 static const int32_t PRECISION_RAW_X_FLAT = 16;
6469 static const int32_t PRECISION_RAW_Y_FLAT = 32;
6470
6471 static const int32_t PRECISION_RAW_X_FUZZ = 4;
6472 static const int32_t PRECISION_RAW_Y_FUZZ = 8;
6473
Prabir Pradhana9df3162022-12-05 23:57:27 +00006474 static const std::array<Point, 4> kRawCorners;
6475};
6476
6477const std::array<Point, 4> TouchscreenPrecisionTestsFixture::kRawCorners = {{
6478 {PRECISION_RAW_X_MIN, PRECISION_RAW_Y_MIN}, // left-top
6479 {PRECISION_RAW_X_MAX, PRECISION_RAW_Y_MIN}, // right-top
6480 {PRECISION_RAW_X_MAX, PRECISION_RAW_Y_MAX}, // right-bottom
6481 {PRECISION_RAW_X_MIN, PRECISION_RAW_Y_MAX}, // left-bottom
6482}};
6483
6484// Tests for how the touchscreen is oriented relative to the natural orientation of the display.
6485// For example, if a touchscreen is configured with an orientation of 90 degrees, it is a portrait
6486// touchscreen panel that is used on a device whose natural display orientation is in landscape.
6487TEST_P(TouchscreenPrecisionTestsFixture, OrientationPrecision) {
6488 enum class Orientation {
6489 ORIENTATION_0 = ui::toRotationInt(ui::ROTATION_0),
6490 ORIENTATION_90 = ui::toRotationInt(ui::ROTATION_90),
6491 ORIENTATION_180 = ui::toRotationInt(ui::ROTATION_180),
6492 ORIENTATION_270 = ui::toRotationInt(ui::ROTATION_270),
6493 ftl_last = ORIENTATION_270,
6494 };
6495 using Orientation::ORIENTATION_0, Orientation::ORIENTATION_90, Orientation::ORIENTATION_180,
6496 Orientation::ORIENTATION_270;
6497 static const std::map<Orientation, std::array<vec2, 4> /*mappedCorners*/> kMappedCorners = {
6498 {ORIENTATION_0, {{{0, 0}, {479.5, 0}, {479.5, 799.75}, {0, 799.75}}}},
6499 {ORIENTATION_90, {{{0, 479.5}, {0, 0}, {799.75, 0}, {799.75, 479.5}}}},
6500 {ORIENTATION_180, {{{479.5, 799.75}, {0, 799.75}, {0, 0}, {479.5, 0}}}},
6501 {ORIENTATION_270, {{{799.75, 0}, {799.75, 479.5}, {0, 479.5}, {0, 0}}}},
6502 };
6503
6504 const auto touchscreenOrientation = static_cast<Orientation>(ui::toRotationInt(GetParam()));
6505
6506 // Configure the touchscreen as being installed in the one of the four different orientations
6507 // relative to the display.
6508 addConfigurationProperty("touch.deviceType", "touchScreen");
6509 addConfigurationProperty("touch.orientation", ftl::enum_string(touchscreenOrientation).c_str());
6510 prepareDisplay(ui::ROTATION_0);
6511
Arpit Singha8c236b2023-04-25 13:56:05 +00006512 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhana9df3162022-12-05 23:57:27 +00006513
6514 // If the touchscreen is installed in a rotated orientation relative to the display (i.e. in
6515 // orientations of either 90 or 270) this means the display's natural resolution will be
6516 // flipped.
6517 const bool displayRotated =
6518 touchscreenOrientation == ORIENTATION_90 || touchscreenOrientation == ORIENTATION_270;
6519 const int32_t width = displayRotated ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
6520 const int32_t height = displayRotated ? DISPLAY_WIDTH : DISPLAY_HEIGHT;
6521 const Rect physicalFrame{0, 0, width, height};
6522 configurePhysicalDisplay(ui::ROTATION_0, physicalFrame, width, height);
6523
6524 const auto& expectedPoints = kMappedCorners.at(touchscreenOrientation);
6525 const float expectedPrecisionX = displayRotated ? 4 : 2;
6526 const float expectedPrecisionY = displayRotated ? 2 : 4;
6527
6528 // Test all four corners.
6529 for (int i = 0; i < 4; i++) {
6530 const auto& raw = kRawCorners[i];
6531 processDown(mapper, raw.x, raw.y);
6532 processSync(mapper);
6533 const auto& expected = expectedPoints[i];
6534 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6535 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6536 WithCoords(expected.x, expected.y),
6537 WithPrecision(expectedPrecisionX, expectedPrecisionY))))
6538 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6539 << "with touchscreen orientation "
6540 << ftl::enum_string(touchscreenOrientation).c_str() << ", expected point ("
6541 << expected.x << ", " << expected.y << ").";
6542 processUp(mapper);
6543 processSync(mapper);
6544 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6545 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6546 WithCoords(expected.x, expected.y))));
6547 }
6548}
6549
Prabir Pradhan82687402022-12-06 01:32:53 +00006550TEST_P(TouchscreenPrecisionTestsFixture, RotationPrecisionWhenOrientationAware) {
6551 static const std::map<ui::Rotation /*rotation*/, std::array<vec2, 4> /*mappedCorners*/>
6552 kMappedCorners = {
6553 {ui::ROTATION_0, {{{0, 0}, {479.5, 0}, {479.5, 799.75}, {0, 799.75}}}},
6554 {ui::ROTATION_90, {{{0.5, 0}, {480, 0}, {480, 799.75}, {0.5, 799.75}}}},
6555 {ui::ROTATION_180, {{{0.5, 0.25}, {480, 0.25}, {480, 800}, {0.5, 800}}}},
6556 {ui::ROTATION_270, {{{0, 0.25}, {479.5, 0.25}, {479.5, 800}, {0, 800}}}},
6557 };
6558
6559 const ui::Rotation displayRotation = GetParam();
6560
6561 addConfigurationProperty("touch.deviceType", "touchScreen");
6562 prepareDisplay(displayRotation);
6563
Arpit Singha8c236b2023-04-25 13:56:05 +00006564 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan82687402022-12-06 01:32:53 +00006565
6566 const auto& expectedPoints = kMappedCorners.at(displayRotation);
6567
6568 // Test all four corners.
6569 for (int i = 0; i < 4; i++) {
6570 const auto& expected = expectedPoints[i];
6571 const auto& raw = kRawCorners[i];
6572 processDown(mapper, raw.x, raw.y);
6573 processSync(mapper);
6574 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6575 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6576 WithCoords(expected.x, expected.y), WithPrecision(2, 4))))
6577 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6578 << "with display rotation " << ui::toCString(displayRotation)
6579 << ", expected point (" << expected.x << ", " << expected.y << ").";
6580 processUp(mapper);
6581 processSync(mapper);
6582 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6583 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6584 WithCoords(expected.x, expected.y))));
6585 }
6586}
6587
Prabir Pradhan3e798762022-12-02 21:02:11 +00006588TEST_P(TouchscreenPrecisionTestsFixture, RotationPrecisionOrientationAwareInOri270) {
6589 static const std::map<ui::Rotation /*orientation*/, std::array<vec2, 4> /*mappedCorners*/>
6590 kMappedCorners = {
6591 {ui::ROTATION_0, {{{799.75, 0}, {799.75, 479.5}, {0, 479.5}, {0, 0}}}},
6592 {ui::ROTATION_90, {{{800, 0}, {800, 479.5}, {0.25, 479.5}, {0.25, 0}}}},
6593 {ui::ROTATION_180, {{{800, 0.5}, {800, 480}, {0.25, 480}, {0.25, 0.5}}}},
6594 {ui::ROTATION_270, {{{799.75, 0.5}, {799.75, 480}, {0, 480}, {0, 0.5}}}},
6595 };
6596
6597 const ui::Rotation displayRotation = GetParam();
6598
6599 addConfigurationProperty("touch.deviceType", "touchScreen");
6600 addConfigurationProperty("touch.orientation", "ORIENTATION_270");
6601
Arpit Singha8c236b2023-04-25 13:56:05 +00006602 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan3e798762022-12-02 21:02:11 +00006603
6604 // Ori 270, so width and height swapped
6605 const Rect physicalFrame{0, 0, DISPLAY_HEIGHT, DISPLAY_WIDTH};
6606 prepareDisplay(displayRotation);
6607 configurePhysicalDisplay(displayRotation, physicalFrame, DISPLAY_HEIGHT, DISPLAY_WIDTH);
6608
6609 const auto& expectedPoints = kMappedCorners.at(displayRotation);
6610
6611 // Test all four corners.
6612 for (int i = 0; i < 4; i++) {
6613 const auto& expected = expectedPoints[i];
6614 const auto& raw = kRawCorners[i];
6615 processDown(mapper, raw.x, raw.y);
6616 processSync(mapper);
6617 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6618 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6619 WithCoords(expected.x, expected.y), WithPrecision(4, 2))))
6620 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6621 << "with display rotation " << ui::toCString(displayRotation)
6622 << ", expected point (" << expected.x << ", " << expected.y << ").";
6623 processUp(mapper);
6624 processSync(mapper);
6625 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6626 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6627 WithCoords(expected.x, expected.y))));
6628 }
6629}
6630
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006631TEST_P(TouchscreenPrecisionTestsFixture, MotionRangesAreOrientedInRotatedDisplay) {
6632 const ui::Rotation displayRotation = GetParam();
6633
6634 addConfigurationProperty("touch.deviceType", "touchScreen");
6635 prepareDisplay(displayRotation);
6636
6637 __attribute__((unused)) SingleTouchInputMapper& mapper =
Arpit Singha8c236b2023-04-25 13:56:05 +00006638 constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006639
6640 const InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
6641 // MotionRanges use display pixels as their units
6642 const auto* xRange = deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHSCREEN);
6643 const auto* yRange = deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_Y, AINPUT_SOURCE_TOUCHSCREEN);
6644
6645 // The MotionRanges should be oriented in the rotated display's coordinate space
6646 const bool displayRotated =
6647 displayRotation == ui::ROTATION_90 || displayRotation == ui::ROTATION_270;
6648
6649 constexpr float MAX_X = 479.5;
6650 constexpr float MAX_Y = 799.75;
6651 EXPECT_EQ(xRange->min, 0.f);
6652 EXPECT_EQ(yRange->min, 0.f);
6653 EXPECT_EQ(xRange->max, displayRotated ? MAX_Y : MAX_X);
6654 EXPECT_EQ(yRange->max, displayRotated ? MAX_X : MAX_Y);
6655
6656 EXPECT_EQ(xRange->flat, 8.f);
6657 EXPECT_EQ(yRange->flat, 8.f);
6658
6659 EXPECT_EQ(xRange->fuzz, 2.f);
6660 EXPECT_EQ(yRange->fuzz, 2.f);
6661
6662 EXPECT_EQ(xRange->resolution, 25.f); // pixels per millimeter
6663 EXPECT_EQ(yRange->resolution, 25.f); // pixels per millimeter
6664}
6665
Prabir Pradhana9df3162022-12-05 23:57:27 +00006666// Run the precision tests for all rotations.
6667INSTANTIATE_TEST_SUITE_P(TouchscreenPrecisionTests, TouchscreenPrecisionTestsFixture,
6668 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
6669 ui::ROTATION_270),
6670 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
6671 return ftl::enum_string(testParamInfo.param);
6672 });
6673
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006674// --- ExternalStylusFusionTest ---
6675
6676class ExternalStylusFusionTest : public SingleTouchInputMapperTest {
6677public:
6678 SingleTouchInputMapper& initializeInputMapperWithExternalStylus() {
6679 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006680 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006681 prepareButtons();
6682 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006683 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006684
6685 mStylusState.when = ARBITRARY_TIME;
6686 mStylusState.pressure = 0.f;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006687 mStylusState.toolType = ToolType::STYLUS;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006688 mReader->getContext()->setExternalStylusDevices({mExternalStylusDeviceInfo});
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006689 configureDevice(InputReaderConfiguration::Change::EXTERNAL_STYLUS_PRESENCE);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006690 processExternalStylusState(mapper);
6691 return mapper;
6692 }
6693
6694 std::list<NotifyArgs> processExternalStylusState(InputMapper& mapper) {
6695 std::list<NotifyArgs> generatedArgs = mapper.updateExternalStylusState(mStylusState);
6696 for (const NotifyArgs& args : generatedArgs) {
6697 mFakeListener->notify(args);
6698 }
6699 // Loop the reader to flush the input listener queue.
6700 mReader->loopOnce();
6701 return generatedArgs;
6702 }
6703
6704protected:
6705 StylusState mStylusState{};
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006706
6707 void testStartFusedStylusGesture(SingleTouchInputMapper& mapper) {
6708 auto toolTypeSource =
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006709 AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006710
6711 // The first pointer is withheld.
6712 processDown(mapper, 100, 200);
6713 processSync(mapper);
6714 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6715 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6716 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6717
6718 // The external stylus reports pressure. The withheld finger pointer is released as a
6719 // stylus.
6720 mStylusState.pressure = 1.f;
6721 processExternalStylusState(mapper);
6722 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6723 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6724 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6725
6726 // Subsequent pointer events are not withheld.
6727 processMove(mapper, 101, 201);
6728 processSync(mapper);
6729 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6730 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6731
6732 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6733 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6734 }
6735
6736 void testSuccessfulFusionGesture(SingleTouchInputMapper& mapper) {
6737 ASSERT_NO_FATAL_FAILURE(testStartFusedStylusGesture(mapper));
6738
6739 // Releasing the touch pointer ends the gesture.
6740 processUp(mapper);
6741 processSync(mapper);
6742 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006743 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(STYLUS_FUSION_SOURCE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006744 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006745
6746 mStylusState.pressure = 0.f;
6747 processExternalStylusState(mapper);
6748 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6749 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6750 }
6751
6752 void testUnsuccessfulFusionGesture(SingleTouchInputMapper& mapper) {
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006753 // When stylus fusion is not successful, events should be reported with the original source.
6754 // In this case, it is from a touchscreen.
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006755 auto toolTypeSource =
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006756 AllOf(WithSource(AINPUT_SOURCE_TOUCHSCREEN), WithToolType(ToolType::FINGER));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006757
6758 // The first pointer is withheld when an external stylus is connected,
6759 // and a timeout is requested.
6760 processDown(mapper, 100, 200);
6761 processSync(mapper);
6762 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6763 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6764 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6765
6766 // If the timeout expires early, it is requested again.
6767 handleTimeout(mapper, ARBITRARY_TIME + 1);
6768 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6769 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6770
6771 // When the timeout expires, the withheld touch is released as a finger pointer.
6772 handleTimeout(mapper, ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT);
6773 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6774 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6775
6776 // Subsequent pointer events are not withheld.
6777 processMove(mapper, 101, 201);
6778 processSync(mapper);
6779 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6780 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6781 processUp(mapper);
6782 processSync(mapper);
6783 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6784 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP))));
6785
6786 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6787 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6788 }
6789
6790private:
6791 InputDeviceInfo mExternalStylusDeviceInfo{};
6792};
6793
6794TEST_F(ExternalStylusFusionTest, UsesBluetoothStylusSource) {
6795 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006796 ASSERT_EQ(STYLUS_FUSION_SOURCE, mapper.getSources());
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006797}
6798
6799TEST_F(ExternalStylusFusionTest, UnsuccessfulFusion) {
6800 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6801 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6802}
6803
6804TEST_F(ExternalStylusFusionTest, SuccessfulFusion_TouchFirst) {
6805 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6806 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6807}
6808
6809// Test a successful stylus fusion gesture where the pressure is reported by the external
6810// before the touch is reported by the touchscreen.
6811TEST_F(ExternalStylusFusionTest, SuccessfulFusion_PressureFirst) {
6812 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006813 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006814
6815 // The external stylus reports pressure first. It is ignored for now.
6816 mStylusState.pressure = 1.f;
6817 processExternalStylusState(mapper);
6818 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6819 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6820
6821 // When the touch goes down afterwards, it is reported as a stylus pointer.
6822 processDown(mapper, 100, 200);
6823 processSync(mapper);
6824 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6825 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6826 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6827
6828 processMove(mapper, 101, 201);
6829 processSync(mapper);
6830 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6831 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6832 processUp(mapper);
6833 processSync(mapper);
6834 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6835 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP))));
6836
6837 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6838 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6839}
6840
6841TEST_F(ExternalStylusFusionTest, FusionIsRepeatedForEachNewGesture) {
6842 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6843
6844 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6845 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6846
6847 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6848 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6849 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6850 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6851}
6852
6853TEST_F(ExternalStylusFusionTest, FusedPointerReportsPressureChanges) {
6854 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006855 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006856
6857 mStylusState.pressure = 0.8f;
6858 processExternalStylusState(mapper);
6859 processDown(mapper, 100, 200);
6860 processSync(mapper);
6861 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6862 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6863 WithPressure(0.8f))));
6864 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6865
6866 // The external stylus reports a pressure change. We wait for some time for a touch event.
6867 mStylusState.pressure = 0.6f;
6868 processExternalStylusState(mapper);
6869 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6870 ASSERT_NO_FATAL_FAILURE(
6871 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6872
6873 // If a touch is reported within the timeout, it reports the updated pressure.
6874 processMove(mapper, 101, 201);
6875 processSync(mapper);
6876 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6877 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6878 WithPressure(0.6f))));
6879 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6880
6881 // There is another pressure change.
6882 mStylusState.pressure = 0.5f;
6883 processExternalStylusState(mapper);
6884 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6885 ASSERT_NO_FATAL_FAILURE(
6886 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6887
6888 // If a touch is not reported within the timeout, a move event is generated to report
6889 // the new pressure.
6890 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
6891 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6892 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6893 WithPressure(0.5f))));
6894
6895 // If a zero pressure is reported before the touch goes up, the previous pressure value is
6896 // repeated indefinitely.
6897 mStylusState.pressure = 0.0f;
6898 processExternalStylusState(mapper);
6899 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6900 ASSERT_NO_FATAL_FAILURE(
6901 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6902 processMove(mapper, 102, 202);
6903 processSync(mapper);
6904 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6905 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6906 WithPressure(0.5f))));
6907 processMove(mapper, 103, 203);
6908 processSync(mapper);
6909 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6910 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6911 WithPressure(0.5f))));
6912
6913 processUp(mapper);
6914 processSync(mapper);
6915 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006916 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(STYLUS_FUSION_SOURCE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006917 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006918
6919 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6920 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6921}
6922
6923TEST_F(ExternalStylusFusionTest, FusedPointerReportsToolTypeChanges) {
6924 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006925 auto source = WithSource(STYLUS_FUSION_SOURCE);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006926
6927 mStylusState.pressure = 1.f;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006928 mStylusState.toolType = ToolType::ERASER;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006929 processExternalStylusState(mapper);
6930 processDown(mapper, 100, 200);
6931 processSync(mapper);
6932 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6933 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006934 WithToolType(ToolType::ERASER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006935 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6936
6937 // The external stylus reports a tool change. We wait for some time for a touch event.
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006938 mStylusState.toolType = ToolType::STYLUS;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006939 processExternalStylusState(mapper);
6940 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6941 ASSERT_NO_FATAL_FAILURE(
6942 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6943
6944 // If a touch is reported within the timeout, it reports the updated pressure.
6945 processMove(mapper, 101, 201);
6946 processSync(mapper);
6947 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6948 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006949 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006950 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6951
6952 // There is another tool type change.
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006953 mStylusState.toolType = ToolType::FINGER;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006954 processExternalStylusState(mapper);
6955 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6956 ASSERT_NO_FATAL_FAILURE(
6957 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6958
6959 // If a touch is not reported within the timeout, a move event is generated to report
6960 // the new tool type.
6961 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
6962 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6963 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006964 WithToolType(ToolType::FINGER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006965
6966 processUp(mapper);
6967 processSync(mapper);
6968 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6969 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006970 WithToolType(ToolType::FINGER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006971
6972 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6973 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6974}
6975
6976TEST_F(ExternalStylusFusionTest, FusedPointerReportsButtons) {
6977 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006978 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006979
6980 ASSERT_NO_FATAL_FAILURE(testStartFusedStylusGesture(mapper));
6981
6982 // The external stylus reports a button change. We wait for some time for a touch event.
6983 mStylusState.buttons = AMOTION_EVENT_BUTTON_STYLUS_PRIMARY;
6984 processExternalStylusState(mapper);
6985 ASSERT_NO_FATAL_FAILURE(
6986 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6987
6988 // If a touch is reported within the timeout, it reports the updated button state.
6989 processMove(mapper, 101, 201);
6990 processSync(mapper);
6991 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6992 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6993 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6994 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6995 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
6996 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6997 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6998
6999 // The button is now released.
7000 mStylusState.buttons = 0;
7001 processExternalStylusState(mapper);
7002 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7003 ASSERT_NO_FATAL_FAILURE(
7004 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
7005
7006 // If a touch is not reported within the timeout, a move event is generated to report
7007 // the new button state.
7008 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007009 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
7010 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
7011 WithButtonState(0))));
7012 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhan124ea442022-10-28 20:27:44 +00007013 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
7014 WithButtonState(0))));
7015
7016 processUp(mapper);
7017 processSync(mapper);
7018 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007019 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
7020
7021 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7022 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7023}
7024
Michael Wrightd02c5b62014-02-10 15:10:22 -08007025// --- MultiTouchInputMapperTest ---
7026
7027class MultiTouchInputMapperTest : public TouchInputMapperTest {
7028protected:
7029 void prepareAxes(int axes);
7030
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007031 void processPosition(MultiTouchInputMapper& mapper, int32_t x, int32_t y);
7032 void processTouchMajor(MultiTouchInputMapper& mapper, int32_t touchMajor);
7033 void processTouchMinor(MultiTouchInputMapper& mapper, int32_t touchMinor);
7034 void processToolMajor(MultiTouchInputMapper& mapper, int32_t toolMajor);
7035 void processToolMinor(MultiTouchInputMapper& mapper, int32_t toolMinor);
7036 void processOrientation(MultiTouchInputMapper& mapper, int32_t orientation);
7037 void processPressure(MultiTouchInputMapper& mapper, int32_t pressure);
7038 void processDistance(MultiTouchInputMapper& mapper, int32_t distance);
7039 void processId(MultiTouchInputMapper& mapper, int32_t id);
7040 void processSlot(MultiTouchInputMapper& mapper, int32_t slot);
7041 void processToolType(MultiTouchInputMapper& mapper, int32_t toolType);
7042 void processKey(MultiTouchInputMapper& mapper, int32_t code, int32_t value);
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00007043 void processHidUsage(MultiTouchInputMapper& mapper, int32_t usageCode, int32_t value);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007044 void processMTSync(MultiTouchInputMapper& mapper);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00007045 void processSync(MultiTouchInputMapper& mapper, nsecs_t eventTime = ARBITRARY_TIME,
7046 nsecs_t readTime = READ_TIME);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007047};
7048
7049void MultiTouchInputMapperTest::prepareAxes(int axes) {
7050 if (axes & POSITION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007051 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
7052 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007053 }
7054 if (axes & TOUCH) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007055 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN,
7056 RAW_TOUCH_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007057 if (axes & MINOR) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007058 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN,
7059 RAW_TOUCH_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007060 }
7061 }
7062 if (axes & TOOL) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007063 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7064 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007065 if (axes & MINOR) {
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007066 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MIN,
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007067 RAW_TOOL_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007068 }
7069 }
7070 if (axes & ORIENTATION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007071 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_ORIENTATION, RAW_ORIENTATION_MIN,
7072 RAW_ORIENTATION_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007073 }
7074 if (axes & PRESSURE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007075 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_PRESSURE, RAW_PRESSURE_MIN,
7076 RAW_PRESSURE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007077 }
7078 if (axes & DISTANCE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007079 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_DISTANCE, RAW_DISTANCE_MIN,
7080 RAW_DISTANCE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007081 }
7082 if (axes & ID) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007083 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TRACKING_ID, RAW_ID_MIN, RAW_ID_MAX, 0,
7084 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007085 }
7086 if (axes & SLOT) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007087 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_SLOT, RAW_SLOT_MIN, RAW_SLOT_MAX, 0, 0);
7088 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007089 }
7090 if (axes & TOOL_TYPE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007091 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007092 }
7093}
7094
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007095void MultiTouchInputMapperTest::processPosition(MultiTouchInputMapper& mapper, int32_t x,
7096 int32_t y) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007097 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
7098 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007099}
7100
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007101void MultiTouchInputMapperTest::processTouchMajor(MultiTouchInputMapper& mapper,
7102 int32_t touchMajor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007103 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOUCH_MAJOR, touchMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007104}
7105
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007106void MultiTouchInputMapperTest::processTouchMinor(MultiTouchInputMapper& mapper,
7107 int32_t touchMinor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007108 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOUCH_MINOR, touchMinor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007109}
7110
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007111void MultiTouchInputMapperTest::processToolMajor(MultiTouchInputMapper& mapper, int32_t toolMajor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007112 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_WIDTH_MAJOR, toolMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007113}
7114
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007115void MultiTouchInputMapperTest::processToolMinor(MultiTouchInputMapper& mapper, int32_t toolMinor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007116 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_WIDTH_MINOR, toolMinor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007117}
7118
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007119void MultiTouchInputMapperTest::processOrientation(MultiTouchInputMapper& mapper,
7120 int32_t orientation) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007121 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_ORIENTATION, orientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007122}
7123
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007124void MultiTouchInputMapperTest::processPressure(MultiTouchInputMapper& mapper, int32_t pressure) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007125 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_PRESSURE, pressure);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007126}
7127
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007128void MultiTouchInputMapperTest::processDistance(MultiTouchInputMapper& mapper, int32_t distance) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007129 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_DISTANCE, distance);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007130}
7131
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007132void MultiTouchInputMapperTest::processId(MultiTouchInputMapper& mapper, int32_t id) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007133 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TRACKING_ID, id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007134}
7135
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007136void MultiTouchInputMapperTest::processSlot(MultiTouchInputMapper& mapper, int32_t slot) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007137 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_SLOT, slot);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007138}
7139
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007140void MultiTouchInputMapperTest::processToolType(MultiTouchInputMapper& mapper, int32_t toolType) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007141 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOOL_TYPE, toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007142}
7143
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007144void MultiTouchInputMapperTest::processKey(MultiTouchInputMapper& mapper, int32_t code,
7145 int32_t value) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007146 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007147}
7148
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00007149void MultiTouchInputMapperTest::processHidUsage(MultiTouchInputMapper& mapper, int32_t usageCode,
7150 int32_t value) {
7151 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, usageCode);
7152 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, value);
7153}
7154
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007155void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper& mapper) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007156 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_MT_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007157}
7158
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00007159void MultiTouchInputMapperTest::processSync(MultiTouchInputMapper& mapper, nsecs_t eventTime,
7160 nsecs_t readTime) {
7161 process(mapper, eventTime, readTime, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007162}
7163
Michael Wrightd02c5b62014-02-10 15:10:22 -08007164TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackingIds) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007165 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007166 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007167 prepareAxes(POSITION);
7168 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007169 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007170
arthurhungdcef2dc2020-08-11 14:47:50 +08007171 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007172
7173 NotifyMotionArgs motionArgs;
7174
7175 // Two fingers down at once.
7176 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7177 processPosition(mapper, x1, y1);
7178 processMTSync(mapper);
7179 processPosition(mapper, x2, y2);
7180 processMTSync(mapper);
7181 processSync(mapper);
7182
7183 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7184 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7185 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7186 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7187 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7188 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
7189 ASSERT_EQ(0, motionArgs.flags);
7190 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7191 ASSERT_EQ(0, motionArgs.buttonState);
7192 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007193 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007194 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007195 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007196 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7197 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7198 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7199 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7200 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7201
7202 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7203 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7204 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7205 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7206 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007207 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007208 ASSERT_EQ(0, motionArgs.flags);
7209 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7210 ASSERT_EQ(0, motionArgs.buttonState);
7211 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007212 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007213 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007214 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007215 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007216 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007217 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7218 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7219 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7220 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7221 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7222 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7223 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7224
7225 // Move.
7226 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7227 processPosition(mapper, x1, y1);
7228 processMTSync(mapper);
7229 processPosition(mapper, x2, y2);
7230 processMTSync(mapper);
7231 processSync(mapper);
7232
7233 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7234 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7235 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7236 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7237 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7238 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7239 ASSERT_EQ(0, motionArgs.flags);
7240 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7241 ASSERT_EQ(0, motionArgs.buttonState);
7242 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007243 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007244 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007245 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007246 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007247 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007248 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7249 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7250 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7251 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7252 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7253 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7254 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7255
7256 // First finger up.
7257 x2 += 15; y2 -= 20;
7258 processPosition(mapper, x2, y2);
7259 processMTSync(mapper);
7260 processSync(mapper);
7261
7262 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7263 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7264 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7265 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7266 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007267 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007268 ASSERT_EQ(0, motionArgs.flags);
7269 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7270 ASSERT_EQ(0, motionArgs.buttonState);
7271 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007272 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007273 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007274 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007275 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007276 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007277 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7278 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7279 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7280 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7281 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7282 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7283 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7284
7285 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7286 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7287 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7288 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7289 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7290 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7291 ASSERT_EQ(0, motionArgs.flags);
7292 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7293 ASSERT_EQ(0, motionArgs.buttonState);
7294 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007295 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007296 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007297 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007298 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7299 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7300 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7301 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7302 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7303
7304 // Move.
7305 x2 += 20; y2 -= 25;
7306 processPosition(mapper, x2, y2);
7307 processMTSync(mapper);
7308 processSync(mapper);
7309
7310 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7311 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7312 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7313 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7314 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7315 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7316 ASSERT_EQ(0, motionArgs.flags);
7317 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7318 ASSERT_EQ(0, motionArgs.buttonState);
7319 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007320 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007321 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007322 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007323 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7324 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7325 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7326 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7327 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7328
7329 // New finger down.
7330 int32_t x3 = 700, y3 = 300;
7331 processPosition(mapper, x2, y2);
7332 processMTSync(mapper);
7333 processPosition(mapper, x3, y3);
7334 processMTSync(mapper);
7335 processSync(mapper);
7336
7337 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7338 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7339 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7340 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7341 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007342 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007343 ASSERT_EQ(0, motionArgs.flags);
7344 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7345 ASSERT_EQ(0, motionArgs.buttonState);
7346 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007347 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007348 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007349 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007350 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007351 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007352 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7353 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7354 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7355 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7356 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7357 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7358 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7359
7360 // Second finger up.
7361 x3 += 30; y3 -= 20;
7362 processPosition(mapper, x3, y3);
7363 processMTSync(mapper);
7364 processSync(mapper);
7365
7366 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7367 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7368 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7369 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7370 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007371 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007372 ASSERT_EQ(0, motionArgs.flags);
7373 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7374 ASSERT_EQ(0, motionArgs.buttonState);
7375 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007376 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007377 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007378 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007379 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007380 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007381 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7382 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7383 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7384 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7385 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7386 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7387 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7388
7389 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7390 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7391 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7392 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7393 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7394 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7395 ASSERT_EQ(0, motionArgs.flags);
7396 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7397 ASSERT_EQ(0, motionArgs.buttonState);
7398 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007399 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007400 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007401 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007402 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7403 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7404 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7405 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7406 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7407
7408 // Last finger up.
7409 processMTSync(mapper);
7410 processSync(mapper);
7411
7412 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7413 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7414 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7415 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7416 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7417 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
7418 ASSERT_EQ(0, motionArgs.flags);
7419 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7420 ASSERT_EQ(0, motionArgs.buttonState);
7421 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007422 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007423 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007424 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007425 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7426 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7427 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7428 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7429 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7430
7431 // Should not have sent any more keys or motions.
7432 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7433 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7434}
7435
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007436TEST_F(MultiTouchInputMapperTest, AxisResolution_IsPopulated) {
7437 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007438 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007439
7440 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, /*flat*/ 0,
7441 /*fuzz*/ 0, /*resolution*/ 10);
7442 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, /*flat*/ 0,
7443 /*fuzz*/ 0, /*resolution*/ 11);
7444 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX,
7445 /*flat*/ 0, /*fuzz*/ 0, /*resolution*/ 12);
7446 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX,
7447 /*flat*/ 0, /*fuzz*/ 0, /*resolution*/ 13);
7448 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7449 /*flat*/ 0, /*flat*/ 0, /*resolution*/ 14);
7450 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7451 /*flat*/ 0, /*flat*/ 0, /*resolution*/ 15);
7452
Arpit Singha8c236b2023-04-25 13:56:05 +00007453 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007454
7455 // X and Y axes
7456 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_X, 10 / X_PRECISION);
7457 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_Y, 11 / Y_PRECISION);
7458 // Touch major and minor
7459 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOUCH_MAJOR, 12 * GEOMETRIC_SCALE);
7460 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOUCH_MINOR, 13 * GEOMETRIC_SCALE);
7461 // Tool major and minor
7462 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOOL_MAJOR, 14 * GEOMETRIC_SCALE);
7463 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOOL_MINOR, 15 * GEOMETRIC_SCALE);
7464}
7465
7466TEST_F(MultiTouchInputMapperTest, TouchMajorAndMinorAxes_DoNotAppearIfNotSupported) {
7467 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007468 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007469
7470 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, /*flat*/ 0,
7471 /*fuzz*/ 0, /*resolution*/ 10);
7472 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, /*flat*/ 0,
7473 /*fuzz*/ 0, /*resolution*/ 11);
7474
7475 // We do not add ABS_MT_TOUCH_MAJOR / MINOR or ABS_MT_WIDTH_MAJOR / MINOR axes
7476
Arpit Singha8c236b2023-04-25 13:56:05 +00007477 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007478
7479 // Touch major and minor
7480 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOUCH_MAJOR);
7481 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOUCH_MINOR);
7482 // Tool major and minor
7483 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOOL_MAJOR);
7484 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOOL_MINOR);
7485}
7486
Michael Wrightd02c5b62014-02-10 15:10:22 -08007487TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingIds) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007488 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007489 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007490 prepareAxes(POSITION | ID);
7491 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007492 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007493
arthurhungdcef2dc2020-08-11 14:47:50 +08007494 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007495
7496 NotifyMotionArgs motionArgs;
7497
7498 // Two fingers down at once.
7499 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7500 processPosition(mapper, x1, y1);
7501 processId(mapper, 1);
7502 processMTSync(mapper);
7503 processPosition(mapper, x2, y2);
7504 processId(mapper, 2);
7505 processMTSync(mapper);
7506 processSync(mapper);
7507
7508 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7509 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007510 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007511 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007512 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007513 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7514 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7515
7516 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007517 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007518 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007519 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007520 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007521 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007522 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007523 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7524 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7525 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7526 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7527
7528 // Move.
7529 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7530 processPosition(mapper, x1, y1);
7531 processId(mapper, 1);
7532 processMTSync(mapper);
7533 processPosition(mapper, x2, y2);
7534 processId(mapper, 2);
7535 processMTSync(mapper);
7536 processSync(mapper);
7537
7538 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7539 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007540 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007541 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007542 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007543 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007544 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007545 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7546 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7547 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7548 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7549
7550 // First finger up.
7551 x2 += 15; y2 -= 20;
7552 processPosition(mapper, x2, y2);
7553 processId(mapper, 2);
7554 processMTSync(mapper);
7555 processSync(mapper);
7556
7557 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007558 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007559 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007560 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007561 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007562 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007563 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007564 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7565 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7566 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7567 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7568
7569 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7570 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007571 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007572 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007573 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007574 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7575 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7576
7577 // Move.
7578 x2 += 20; y2 -= 25;
7579 processPosition(mapper, x2, y2);
7580 processId(mapper, 2);
7581 processMTSync(mapper);
7582 processSync(mapper);
7583
7584 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7585 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007586 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007587 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007588 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007589 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7590 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7591
7592 // New finger down.
7593 int32_t x3 = 700, y3 = 300;
7594 processPosition(mapper, x2, y2);
7595 processId(mapper, 2);
7596 processMTSync(mapper);
7597 processPosition(mapper, x3, y3);
7598 processId(mapper, 3);
7599 processMTSync(mapper);
7600 processSync(mapper);
7601
7602 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007603 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007604 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007605 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007606 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007607 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007608 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007609 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7610 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7611 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7612 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7613
7614 // Second finger up.
7615 x3 += 30; y3 -= 20;
7616 processPosition(mapper, x3, y3);
7617 processId(mapper, 3);
7618 processMTSync(mapper);
7619 processSync(mapper);
7620
7621 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007622 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007623 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007624 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007625 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007626 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007627 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007628 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7629 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7630 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7631 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7632
7633 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7634 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007635 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007636 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007637 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007638 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7639 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7640
7641 // Last finger up.
7642 processMTSync(mapper);
7643 processSync(mapper);
7644
7645 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7646 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007647 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007648 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007649 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007650 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7651 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7652
7653 // Should not have sent any more keys or motions.
7654 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7655 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7656}
7657
7658TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithSlots) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007659 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007660 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007661 prepareAxes(POSITION | ID | SLOT);
7662 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007663 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007664
arthurhungdcef2dc2020-08-11 14:47:50 +08007665 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007666
7667 NotifyMotionArgs motionArgs;
7668
7669 // Two fingers down at once.
7670 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7671 processPosition(mapper, x1, y1);
7672 processId(mapper, 1);
7673 processSlot(mapper, 1);
7674 processPosition(mapper, x2, y2);
7675 processId(mapper, 2);
7676 processSync(mapper);
7677
7678 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7679 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007680 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007681 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007682 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007683 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7684 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7685
7686 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007687 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007688 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007689 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007690 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007691 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007692 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007693 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7694 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7695 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7696 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7697
7698 // Move.
7699 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7700 processSlot(mapper, 0);
7701 processPosition(mapper, x1, y1);
7702 processSlot(mapper, 1);
7703 processPosition(mapper, x2, y2);
7704 processSync(mapper);
7705
7706 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7707 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007708 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007709 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007710 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007711 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007712 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007713 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7714 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7715 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7716 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7717
7718 // First finger up.
7719 x2 += 15; y2 -= 20;
7720 processSlot(mapper, 0);
7721 processId(mapper, -1);
7722 processSlot(mapper, 1);
7723 processPosition(mapper, x2, y2);
7724 processSync(mapper);
7725
7726 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007727 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007728 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007729 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007730 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007731 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007732 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007733 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7734 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7735 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7736 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7737
7738 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7739 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007740 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007741 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007742 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007743 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7744 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7745
7746 // Move.
7747 x2 += 20; y2 -= 25;
7748 processPosition(mapper, x2, y2);
7749 processSync(mapper);
7750
7751 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7752 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007753 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007754 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007755 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007756 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7757 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7758
7759 // New finger down.
7760 int32_t x3 = 700, y3 = 300;
7761 processPosition(mapper, x2, y2);
7762 processSlot(mapper, 0);
7763 processId(mapper, 3);
7764 processPosition(mapper, x3, y3);
7765 processSync(mapper);
7766
7767 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007768 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007769 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007770 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007771 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007772 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007773 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007774 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7775 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7776 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7777 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7778
7779 // Second finger up.
7780 x3 += 30; y3 -= 20;
7781 processSlot(mapper, 1);
7782 processId(mapper, -1);
7783 processSlot(mapper, 0);
7784 processPosition(mapper, x3, y3);
7785 processSync(mapper);
7786
7787 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007788 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007789 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007790 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007791 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007792 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007793 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007794 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7795 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7796 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7797 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7798
7799 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7800 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007801 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007802 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007803 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007804 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7805 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7806
7807 // Last finger up.
7808 processId(mapper, -1);
7809 processSync(mapper);
7810
7811 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7812 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007813 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007814 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007815 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007816 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7817 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7818
7819 // Should not have sent any more keys or motions.
7820 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7821 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7822}
7823
7824TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007825 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007826 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007827 prepareAxes(POSITION | TOUCH | TOOL | PRESSURE | ORIENTATION | ID | MINOR | DISTANCE);
Arpit Singha8c236b2023-04-25 13:56:05 +00007828 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007829
7830 // These calculations are based on the input device calibration documentation.
7831 int32_t rawX = 100;
7832 int32_t rawY = 200;
7833 int32_t rawTouchMajor = 7;
7834 int32_t rawTouchMinor = 6;
7835 int32_t rawToolMajor = 9;
7836 int32_t rawToolMinor = 8;
7837 int32_t rawPressure = 11;
7838 int32_t rawDistance = 0;
7839 int32_t rawOrientation = 3;
7840 int32_t id = 5;
7841
7842 float x = toDisplayX(rawX);
7843 float y = toDisplayY(rawY);
7844 float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
7845 float size = avg(rawTouchMajor, rawTouchMinor) / RAW_TOUCH_MAX;
7846 float toolMajor = float(rawToolMajor) * GEOMETRIC_SCALE;
7847 float toolMinor = float(rawToolMinor) * GEOMETRIC_SCALE;
7848 float touchMajor = float(rawTouchMajor) * GEOMETRIC_SCALE;
7849 float touchMinor = float(rawTouchMinor) * GEOMETRIC_SCALE;
7850 float orientation = float(rawOrientation) / RAW_ORIENTATION_MAX * M_PI_2;
7851 float distance = float(rawDistance);
7852
7853 processPosition(mapper, rawX, rawY);
7854 processTouchMajor(mapper, rawTouchMajor);
7855 processTouchMinor(mapper, rawTouchMinor);
7856 processToolMajor(mapper, rawToolMajor);
7857 processToolMinor(mapper, rawToolMinor);
7858 processPressure(mapper, rawPressure);
7859 processOrientation(mapper, rawOrientation);
7860 processDistance(mapper, rawDistance);
7861 processId(mapper, id);
7862 processMTSync(mapper);
7863 processSync(mapper);
7864
7865 NotifyMotionArgs args;
7866 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7867 ASSERT_EQ(0, args.pointerProperties[0].id);
7868 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7869 x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor,
7870 orientation, distance));
Prabir Pradhan9a53b552024-06-04 02:59:40 +00007871 ASSERT_EQ(args.flags, AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007872}
7873
7874TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_GeometricCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007875 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007876 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007877 prepareAxes(POSITION | TOUCH | TOOL | MINOR);
7878 addConfigurationProperty("touch.size.calibration", "geometric");
Arpit Singha8c236b2023-04-25 13:56:05 +00007879 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007880
7881 // These calculations are based on the input device calibration documentation.
7882 int32_t rawX = 100;
7883 int32_t rawY = 200;
7884 int32_t rawTouchMajor = 140;
7885 int32_t rawTouchMinor = 120;
7886 int32_t rawToolMajor = 180;
7887 int32_t rawToolMinor = 160;
7888
7889 float x = toDisplayX(rawX);
7890 float y = toDisplayY(rawY);
7891 float size = avg(rawTouchMajor, rawTouchMinor) / RAW_TOUCH_MAX;
7892 float toolMajor = float(rawToolMajor) * GEOMETRIC_SCALE;
7893 float toolMinor = float(rawToolMinor) * GEOMETRIC_SCALE;
7894 float touchMajor = float(rawTouchMajor) * GEOMETRIC_SCALE;
7895 float touchMinor = float(rawTouchMinor) * GEOMETRIC_SCALE;
7896
7897 processPosition(mapper, rawX, rawY);
7898 processTouchMajor(mapper, rawTouchMajor);
7899 processTouchMinor(mapper, rawTouchMinor);
7900 processToolMajor(mapper, rawToolMajor);
7901 processToolMinor(mapper, rawToolMinor);
7902 processMTSync(mapper);
7903 processSync(mapper);
7904
7905 NotifyMotionArgs args;
7906 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7907 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7908 x, y, 1.0f, size, touchMajor, touchMinor, toolMajor, toolMinor, 0, 0));
7909}
7910
7911TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_SummedLinearCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007912 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007913 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007914 prepareAxes(POSITION | TOUCH | TOOL);
7915 addConfigurationProperty("touch.size.calibration", "diameter");
7916 addConfigurationProperty("touch.size.scale", "10");
7917 addConfigurationProperty("touch.size.bias", "160");
7918 addConfigurationProperty("touch.size.isSummed", "1");
Arpit Singha8c236b2023-04-25 13:56:05 +00007919 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007920
7921 // These calculations are based on the input device calibration documentation.
7922 // Note: We only provide a single common touch/tool value because the device is assumed
7923 // not to emit separate values for each pointer (isSummed = 1).
7924 int32_t rawX = 100;
7925 int32_t rawY = 200;
7926 int32_t rawX2 = 150;
7927 int32_t rawY2 = 250;
7928 int32_t rawTouchMajor = 5;
7929 int32_t rawToolMajor = 8;
7930
7931 float x = toDisplayX(rawX);
7932 float y = toDisplayY(rawY);
7933 float x2 = toDisplayX(rawX2);
7934 float y2 = toDisplayY(rawY2);
7935 float size = float(rawTouchMajor) / 2 / RAW_TOUCH_MAX;
7936 float touch = float(rawTouchMajor) / 2 * 10.0f + 160.0f;
7937 float tool = float(rawToolMajor) / 2 * 10.0f + 160.0f;
7938
7939 processPosition(mapper, rawX, rawY);
7940 processTouchMajor(mapper, rawTouchMajor);
7941 processToolMajor(mapper, rawToolMajor);
7942 processMTSync(mapper);
7943 processPosition(mapper, rawX2, rawY2);
7944 processTouchMajor(mapper, rawTouchMajor);
7945 processToolMajor(mapper, rawToolMajor);
7946 processMTSync(mapper);
7947 processSync(mapper);
7948
7949 NotifyMotionArgs args;
7950 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7951 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
7952
7953 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007954 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007955 ASSERT_EQ(size_t(2), args.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007956 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7957 x, y, 1.0f, size, touch, touch, tool, tool, 0, 0));
7958 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[1],
7959 x2, y2, 1.0f, size, touch, touch, tool, tool, 0, 0));
7960}
7961
7962TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_AreaCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007963 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007964 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007965 prepareAxes(POSITION | TOUCH | TOOL);
7966 addConfigurationProperty("touch.size.calibration", "area");
7967 addConfigurationProperty("touch.size.scale", "43");
7968 addConfigurationProperty("touch.size.bias", "3");
Arpit Singha8c236b2023-04-25 13:56:05 +00007969 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007970
7971 // These calculations are based on the input device calibration documentation.
7972 int32_t rawX = 100;
7973 int32_t rawY = 200;
7974 int32_t rawTouchMajor = 5;
7975 int32_t rawToolMajor = 8;
7976
7977 float x = toDisplayX(rawX);
7978 float y = toDisplayY(rawY);
7979 float size = float(rawTouchMajor) / RAW_TOUCH_MAX;
7980 float touch = sqrtf(rawTouchMajor) * 43.0f + 3.0f;
7981 float tool = sqrtf(rawToolMajor) * 43.0f + 3.0f;
7982
7983 processPosition(mapper, rawX, rawY);
7984 processTouchMajor(mapper, rawTouchMajor);
7985 processToolMajor(mapper, rawToolMajor);
7986 processMTSync(mapper);
7987 processSync(mapper);
7988
7989 NotifyMotionArgs args;
7990 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7991 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7992 x, y, 1.0f, size, touch, touch, tool, tool, 0, 0));
7993}
7994
7995TEST_F(MultiTouchInputMapperTest, Process_PressureAxis_AmplitudeCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007996 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007997 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007998 prepareAxes(POSITION | PRESSURE);
7999 addConfigurationProperty("touch.pressure.calibration", "amplitude");
8000 addConfigurationProperty("touch.pressure.scale", "0.01");
Arpit Singha8c236b2023-04-25 13:56:05 +00008001 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008002
Michael Wrightaa449c92017-12-13 21:21:43 +00008003 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +00008004 mapper.populateDeviceInfo(info);
Michael Wrightaa449c92017-12-13 21:21:43 +00008005 ASSERT_NO_FATAL_FAILURE(assertMotionRange(info,
8006 AINPUT_MOTION_RANGE_PRESSURE, AINPUT_SOURCE_TOUCHSCREEN,
8007 0.0f, RAW_PRESSURE_MAX * 0.01, 0.0f, 0.0f));
8008
Michael Wrightd02c5b62014-02-10 15:10:22 -08008009 // These calculations are based on the input device calibration documentation.
8010 int32_t rawX = 100;
8011 int32_t rawY = 200;
8012 int32_t rawPressure = 60;
8013
8014 float x = toDisplayX(rawX);
8015 float y = toDisplayY(rawY);
8016 float pressure = float(rawPressure) * 0.01f;
8017
8018 processPosition(mapper, rawX, rawY);
8019 processPressure(mapper, rawPressure);
8020 processMTSync(mapper);
8021 processSync(mapper);
8022
8023 NotifyMotionArgs args;
8024 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8025 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8026 x, y, pressure, 0, 0, 0, 0, 0, 0, 0));
8027}
8028
8029TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllButtons) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008030 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008031 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008032 prepareAxes(POSITION | ID | SLOT);
Arpit Singha8c236b2023-04-25 13:56:05 +00008033 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008034
8035 NotifyMotionArgs motionArgs;
8036 NotifyKeyArgs keyArgs;
8037
8038 processId(mapper, 1);
8039 processPosition(mapper, 100, 200);
8040 processSync(mapper);
8041 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8042 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8043 ASSERT_EQ(0, motionArgs.buttonState);
8044
8045 // press BTN_LEFT, release BTN_LEFT
8046 processKey(mapper, BTN_LEFT, 1);
8047 processSync(mapper);
8048 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8049 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
8050 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
8051
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008052 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8053 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8054 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
8055
Michael Wrightd02c5b62014-02-10 15:10:22 -08008056 processKey(mapper, BTN_LEFT, 0);
8057 processSync(mapper);
8058 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008059 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008060 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008061
8062 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008063 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008064 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008065
8066 // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
8067 processKey(mapper, BTN_RIGHT, 1);
8068 processKey(mapper, BTN_MIDDLE, 1);
8069 processSync(mapper);
8070 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8071 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
8072 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
8073 motionArgs.buttonState);
8074
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008075 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8076 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8077 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
8078
8079 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8080 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8081 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
8082 motionArgs.buttonState);
8083
Michael Wrightd02c5b62014-02-10 15:10:22 -08008084 processKey(mapper, BTN_RIGHT, 0);
8085 processSync(mapper);
8086 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008087 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008088 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008089
8090 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008091 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008092 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008093
8094 processKey(mapper, BTN_MIDDLE, 0);
8095 processSync(mapper);
8096 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008097 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008098 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008099
8100 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008101 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008102 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008103
8104 // press BTN_BACK, release BTN_BACK
8105 processKey(mapper, BTN_BACK, 1);
8106 processSync(mapper);
8107 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8108 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8109 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008110
Michael Wrightd02c5b62014-02-10 15:10:22 -08008111 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008112 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008113 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
8114
8115 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8116 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8117 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008118
8119 processKey(mapper, BTN_BACK, 0);
8120 processSync(mapper);
8121 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008122 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008123 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008124
8125 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008126 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008127 ASSERT_EQ(0, motionArgs.buttonState);
8128
Michael Wrightd02c5b62014-02-10 15:10:22 -08008129 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8130 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8131 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
8132
8133 // press BTN_SIDE, release BTN_SIDE
8134 processKey(mapper, BTN_SIDE, 1);
8135 processSync(mapper);
8136 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8137 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8138 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008139
Michael Wrightd02c5b62014-02-10 15:10:22 -08008140 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008141 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008142 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
8143
8144 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8145 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8146 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008147
8148 processKey(mapper, BTN_SIDE, 0);
8149 processSync(mapper);
8150 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008151 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008152 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008153
8154 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008155 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008156 ASSERT_EQ(0, motionArgs.buttonState);
8157
Michael Wrightd02c5b62014-02-10 15:10:22 -08008158 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8159 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8160 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
8161
8162 // press BTN_FORWARD, release BTN_FORWARD
8163 processKey(mapper, BTN_FORWARD, 1);
8164 processSync(mapper);
8165 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8166 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8167 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008168
Michael Wrightd02c5b62014-02-10 15:10:22 -08008169 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008170 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008171 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
8172
8173 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8174 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8175 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008176
8177 processKey(mapper, BTN_FORWARD, 0);
8178 processSync(mapper);
8179 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008180 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008181 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008182
8183 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008184 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008185 ASSERT_EQ(0, motionArgs.buttonState);
8186
Michael Wrightd02c5b62014-02-10 15:10:22 -08008187 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8188 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8189 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
8190
8191 // press BTN_EXTRA, release BTN_EXTRA
8192 processKey(mapper, BTN_EXTRA, 1);
8193 processSync(mapper);
8194 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8195 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8196 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008197
Michael Wrightd02c5b62014-02-10 15:10:22 -08008198 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008199 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008200 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
8201
8202 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8203 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8204 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008205
8206 processKey(mapper, BTN_EXTRA, 0);
8207 processSync(mapper);
8208 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008209 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008210 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008211
8212 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008213 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008214 ASSERT_EQ(0, motionArgs.buttonState);
8215
Michael Wrightd02c5b62014-02-10 15:10:22 -08008216 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8217 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8218 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
8219
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008220 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
8221
Michael Wrightd02c5b62014-02-10 15:10:22 -08008222 // press BTN_STYLUS, release BTN_STYLUS
8223 processKey(mapper, BTN_STYLUS, 1);
8224 processSync(mapper);
8225 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8226 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008227 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
8228
8229 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8230 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8231 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008232
8233 processKey(mapper, BTN_STYLUS, 0);
8234 processSync(mapper);
8235 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008236 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008237 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008238
8239 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008240 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008241 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008242
8243 // press BTN_STYLUS2, release BTN_STYLUS2
8244 processKey(mapper, BTN_STYLUS2, 1);
8245 processSync(mapper);
8246 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8247 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008248 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
8249
8250 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8251 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8252 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008253
8254 processKey(mapper, BTN_STYLUS2, 0);
8255 processSync(mapper);
8256 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008257 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008258 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008259
8260 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008261 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008262 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008263
8264 // release touch
8265 processId(mapper, -1);
8266 processSync(mapper);
8267 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8268 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8269 ASSERT_EQ(0, motionArgs.buttonState);
8270}
8271
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008272TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleMappedStylusButtons) {
8273 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008274 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008275 prepareAxes(POSITION | ID | SLOT);
Arpit Singha8c236b2023-04-25 13:56:05 +00008276 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008277
8278 mFakeEventHub->addKey(EVENTHUB_ID, BTN_A, 0, AKEYCODE_STYLUS_BUTTON_PRIMARY, 0);
8279 mFakeEventHub->addKey(EVENTHUB_ID, 0, 0xabcd, AKEYCODE_STYLUS_BUTTON_SECONDARY, 0);
8280
8281 // Touch down.
8282 processId(mapper, 1);
8283 processPosition(mapper, 100, 200);
8284 processSync(mapper);
8285 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8286 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithButtonState(0))));
8287
8288 // Press and release button mapped to the primary stylus button.
8289 processKey(mapper, BTN_A, 1);
8290 processSync(mapper);
8291 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8292 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
8293 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
8294 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8295 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
8296 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
8297
8298 processKey(mapper, BTN_A, 0);
8299 processSync(mapper);
8300 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8301 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithButtonState(0))));
8302 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8303 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
8304
8305 // Press and release the HID usage mapped to the secondary stylus button.
8306 processHidUsage(mapper, 0xabcd, 1);
8307 processSync(mapper);
8308 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8309 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
8310 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY))));
8311 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8312 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
8313 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY))));
8314
8315 processHidUsage(mapper, 0xabcd, 0);
8316 processSync(mapper);
8317 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8318 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithButtonState(0))));
8319 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8320 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
8321
8322 // Release touch.
8323 processId(mapper, -1);
8324 processSync(mapper);
8325 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8326 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
8327}
8328
Michael Wrightd02c5b62014-02-10 15:10:22 -08008329TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008330 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008331 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008332 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00008333 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008334
8335 NotifyMotionArgs motionArgs;
8336
8337 // default tool type is finger
8338 processId(mapper, 1);
8339 processPosition(mapper, 100, 200);
8340 processSync(mapper);
8341 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8342 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008343 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008344
8345 // eraser
8346 processKey(mapper, BTN_TOOL_RUBBER, 1);
8347 processSync(mapper);
8348 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8349 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008350 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008351
8352 // stylus
8353 processKey(mapper, BTN_TOOL_RUBBER, 0);
8354 processKey(mapper, BTN_TOOL_PEN, 1);
8355 processSync(mapper);
8356 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8357 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008358 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008359
8360 // brush
8361 processKey(mapper, BTN_TOOL_PEN, 0);
8362 processKey(mapper, BTN_TOOL_BRUSH, 1);
8363 processSync(mapper);
8364 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8365 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008366 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008367
8368 // pencil
8369 processKey(mapper, BTN_TOOL_BRUSH, 0);
8370 processKey(mapper, BTN_TOOL_PENCIL, 1);
8371 processSync(mapper);
8372 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8373 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008374 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008375
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08008376 // air-brush
Michael Wrightd02c5b62014-02-10 15:10:22 -08008377 processKey(mapper, BTN_TOOL_PENCIL, 0);
8378 processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
8379 processSync(mapper);
8380 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8381 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008382 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008383
8384 // mouse
8385 processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
8386 processKey(mapper, BTN_TOOL_MOUSE, 1);
8387 processSync(mapper);
8388 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8389 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008390 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008391
8392 // lens
8393 processKey(mapper, BTN_TOOL_MOUSE, 0);
8394 processKey(mapper, BTN_TOOL_LENS, 1);
8395 processSync(mapper);
8396 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8397 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008398 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008399
8400 // double-tap
8401 processKey(mapper, BTN_TOOL_LENS, 0);
8402 processKey(mapper, BTN_TOOL_DOUBLETAP, 1);
8403 processSync(mapper);
8404 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8405 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008406 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008407
8408 // triple-tap
8409 processKey(mapper, BTN_TOOL_DOUBLETAP, 0);
8410 processKey(mapper, BTN_TOOL_TRIPLETAP, 1);
8411 processSync(mapper);
8412 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8413 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008414 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008415
8416 // quad-tap
8417 processKey(mapper, BTN_TOOL_TRIPLETAP, 0);
8418 processKey(mapper, BTN_TOOL_QUADTAP, 1);
8419 processSync(mapper);
8420 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8421 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008422 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008423
8424 // finger
8425 processKey(mapper, BTN_TOOL_QUADTAP, 0);
8426 processKey(mapper, BTN_TOOL_FINGER, 1);
8427 processSync(mapper);
8428 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8429 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008430 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008431
8432 // stylus trumps finger
8433 processKey(mapper, BTN_TOOL_PEN, 1);
8434 processSync(mapper);
8435 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8436 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008437 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008438
8439 // eraser trumps stylus
8440 processKey(mapper, BTN_TOOL_RUBBER, 1);
8441 processSync(mapper);
8442 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8443 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008444 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008445
8446 // mouse trumps eraser
8447 processKey(mapper, BTN_TOOL_MOUSE, 1);
8448 processSync(mapper);
8449 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8450 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008451 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008452
8453 // MT tool type trumps BTN tool types: MT_TOOL_FINGER
8454 processToolType(mapper, MT_TOOL_FINGER); // this is the first time we send MT_TOOL_TYPE
8455 processSync(mapper);
8456 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8457 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008458 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008459
8460 // MT tool type trumps BTN tool types: MT_TOOL_PEN
8461 processToolType(mapper, MT_TOOL_PEN);
8462 processSync(mapper);
8463 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8464 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008465 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008466
8467 // back to default tool type
8468 processToolType(mapper, -1); // use a deliberately undefined tool type, for testing
8469 processKey(mapper, BTN_TOOL_MOUSE, 0);
8470 processKey(mapper, BTN_TOOL_RUBBER, 0);
8471 processKey(mapper, BTN_TOOL_PEN, 0);
8472 processKey(mapper, BTN_TOOL_FINGER, 0);
8473 processSync(mapper);
8474 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8475 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008476 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008477}
8478
8479TEST_F(MultiTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008480 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008481 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008482 prepareAxes(POSITION | ID | SLOT);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008483 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00008484 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008485
8486 NotifyMotionArgs motionArgs;
8487
8488 // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0
8489 processId(mapper, 1);
8490 processPosition(mapper, 100, 200);
8491 processSync(mapper);
8492 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8493 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8494 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8495 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8496
8497 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8498 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8499 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8500 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8501
8502 // move a little
8503 processPosition(mapper, 150, 250);
8504 processSync(mapper);
8505 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8506 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8507 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8508 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8509
8510 // down when BTN_TOUCH is pressed, pressure defaults to 1
8511 processKey(mapper, BTN_TOUCH, 1);
8512 processSync(mapper);
8513 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8514 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8515 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8516 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8517
8518 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8519 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8520 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8521 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8522
8523 // up when BTN_TOUCH is released, hover restored
8524 processKey(mapper, BTN_TOUCH, 0);
8525 processSync(mapper);
8526 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8527 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8528 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8529 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8530
8531 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8532 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8533 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8534 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8535
8536 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8537 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8538 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8539 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8540
8541 // exit hover when pointer goes away
8542 processId(mapper, -1);
8543 processSync(mapper);
8544 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8545 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8546 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8547 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8548}
8549
8550TEST_F(MultiTouchInputMapperTest, Process_WhenAbsMTPressureIsPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008551 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008552 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008553 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00008554 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008555
8556 NotifyMotionArgs motionArgs;
8557
8558 // initially hovering because pressure is 0
8559 processId(mapper, 1);
8560 processPosition(mapper, 100, 200);
8561 processPressure(mapper, 0);
8562 processSync(mapper);
8563 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8564 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8565 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8566 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8567
8568 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8569 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8570 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8571 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8572
8573 // move a little
8574 processPosition(mapper, 150, 250);
8575 processSync(mapper);
8576 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8577 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8578 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8579 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8580
8581 // down when pressure becomes non-zero
8582 processPressure(mapper, RAW_PRESSURE_MAX);
8583 processSync(mapper);
8584 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8585 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8586 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8587 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8588
8589 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8590 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8591 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8592 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8593
8594 // up when pressure becomes 0, hover restored
8595 processPressure(mapper, 0);
8596 processSync(mapper);
8597 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8598 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8599 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8600 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8601
8602 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8603 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8604 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8605 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8606
8607 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8608 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8609 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8610 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8611
8612 // exit hover when pointer goes away
8613 processId(mapper, -1);
8614 processSync(mapper);
8615 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8616 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8617 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8618 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8619}
8620
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008621/**
8622 * Set the input device port <--> display port associations, and check that the
8623 * events are routed to the display that matches the display port.
8624 * This can be checked by looking at the displayId of the resulting NotifyMotionArgs.
8625 */
8626TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayPort) {
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008627 const std::string usb2 = "USB2";
8628 const uint8_t hdmi1 = 0;
8629 const uint8_t hdmi2 = 1;
8630 const std::string secondaryUniqueId = "uniqueId2";
Michael Wrightfe3de7d2020-07-02 19:05:30 +01008631 constexpr ViewportType type = ViewportType::EXTERNAL;
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008632
8633 addConfigurationProperty("touch.deviceType", "touchScreen");
8634 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008635 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008636
8637 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
8638 mFakePolicy->addInputPortAssociation(usb2, hdmi2);
8639
8640 // We are intentionally not adding the viewport for display 1 yet. Since the port association
8641 // for this input device is specified, and the matching viewport is not present,
8642 // the input device should be disabled (at the mapper level).
8643
8644 // Add viewport for display 2 on hdmi2
8645 prepareSecondaryDisplay(type, hdmi2);
8646 // Send a touch event
8647 processPosition(mapper, 100, 100);
8648 processSync(mapper);
8649 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
8650
8651 // Add viewport for display 1 on hdmi1
Michael Wrighta9cf4192022-12-01 23:46:39 +00008652 prepareDisplay(ui::ROTATION_0, hdmi1);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008653 // Send a touch event again
8654 processPosition(mapper, 100, 100);
8655 processSync(mapper);
8656
8657 NotifyMotionArgs args;
8658 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8659 ASSERT_EQ(DISPLAY_ID, args.displayId);
8660}
Michael Wrightd02c5b62014-02-10 15:10:22 -08008661
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008662TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayUniqueId) {
8663 addConfigurationProperty("touch.deviceType", "touchScreen");
8664 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008665 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008666
8667 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID);
8668
Michael Wrighta9cf4192022-12-01 23:46:39 +00008669 prepareDisplay(ui::ROTATION_0);
8670 prepareVirtualDisplay(ui::ROTATION_0);
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008671
8672 // Send a touch event
8673 processPosition(mapper, 100, 100);
8674 processSync(mapper);
8675
8676 NotifyMotionArgs args;
8677 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8678 ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId);
8679}
8680
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008681TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01008682 prepareSecondaryDisplay(ViewportType::EXTERNAL);
Garfield Tan888a6a42020-01-09 11:39:16 -08008683
Michael Wrighta9cf4192022-12-01 23:46:39 +00008684 prepareDisplay(ui::ROTATION_0);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008685 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008686 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008687
Josep del Río2d8c79a2023-01-23 19:33:50 +00008688 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008689
8690 NotifyMotionArgs motionArgs;
8691 processPosition(mapper, 100, 100);
8692 processSync(mapper);
8693
8694 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8695 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008696 ASSERT_EQ(ui::LogicalDisplayId::INVALID, motionArgs.displayId);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008697}
8698
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008699/**
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008700 * Ensure that the readTime is set to the SYN_REPORT value when processing touch events.
8701 */
8702TEST_F(MultiTouchInputMapperTest, Process_SendsReadTime) {
8703 addConfigurationProperty("touch.deviceType", "touchScreen");
8704 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008705 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008706
Michael Wrighta9cf4192022-12-01 23:46:39 +00008707 prepareDisplay(ui::ROTATION_0);
Harry Cutts33476232023-01-30 19:57:29 +00008708 process(mapper, 10, /*readTime=*/11, EV_ABS, ABS_MT_TRACKING_ID, 1);
8709 process(mapper, 15, /*readTime=*/16, EV_ABS, ABS_MT_POSITION_X, 100);
8710 process(mapper, 20, /*readTime=*/21, EV_ABS, ABS_MT_POSITION_Y, 100);
8711 process(mapper, 25, /*readTime=*/26, EV_SYN, SYN_REPORT, 0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008712
8713 NotifyMotionArgs args;
8714 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8715 ASSERT_EQ(26, args.readTime);
8716
Harry Cutts33476232023-01-30 19:57:29 +00008717 process(mapper, 30, /*readTime=*/31, EV_ABS, ABS_MT_POSITION_X, 110);
8718 process(mapper, 30, /*readTime=*/32, EV_ABS, ABS_MT_POSITION_Y, 220);
8719 process(mapper, 30, /*readTime=*/33, EV_SYN, SYN_REPORT, 0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008720
8721 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8722 ASSERT_EQ(33, args.readTime);
8723}
8724
8725/**
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008726 * When the viewport is not active (isActive=false), the touch mapper should be disabled and the
8727 * events should not be delivered to the listener.
8728 */
8729TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreDropped) {
8730 addConfigurationProperty("touch.deviceType", "touchScreen");
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008731 // Don't set touch.enableForInactiveViewport to verify the default behavior.
Michael Wrighta9cf4192022-12-01 23:46:39 +00008732 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008733 /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008734 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008735 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008736 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008737
8738 NotifyMotionArgs motionArgs;
8739 processPosition(mapper, 100, 100);
8740 processSync(mapper);
8741
8742 mFakeListener->assertNotifyMotionWasNotCalled();
8743}
8744
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008745/**
8746 * When the viewport is not active (isActive=false) and touch.enableForInactiveViewport is true,
8747 * the touch mapper can process the events and the events can be delivered to the listener.
8748 */
8749TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreProcessed) {
8750 addConfigurationProperty("touch.deviceType", "touchScreen");
8751 addConfigurationProperty("touch.enableForInactiveViewport", "1");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008752 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008753 /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008754 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008755 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008756 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008757
8758 NotifyMotionArgs motionArgs;
8759 processPosition(mapper, 100, 100);
8760 processSync(mapper);
8761
8762 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8763 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8764}
8765
Josh Thielene986aed2023-06-01 14:17:30 +00008766/**
8767 * When the viewport is deactivated (isActive transitions from true to false),
8768 * and touch.enableForInactiveViewport is false, touches prior to the transition
8769 * should be cancelled.
8770 */
Garfield Tanc734e4f2021-01-15 20:01:39 -08008771TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_AbortTouches) {
8772 addConfigurationProperty("touch.deviceType", "touchScreen");
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008773 addConfigurationProperty("touch.enableForInactiveViewport", "0");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008774 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008775 /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008776 std::optional<DisplayViewport> optionalDisplayViewport =
8777 mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
8778 ASSERT_TRUE(optionalDisplayViewport.has_value());
8779 DisplayViewport displayViewport = *optionalDisplayViewport;
8780
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008781 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008782 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008783 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Garfield Tanc734e4f2021-01-15 20:01:39 -08008784
8785 // Finger down
8786 int32_t x = 100, y = 100;
8787 processPosition(mapper, x, y);
8788 processSync(mapper);
8789
8790 NotifyMotionArgs motionArgs;
8791 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8792 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8793
8794 // Deactivate display viewport
8795 displayViewport.isActive = false;
8796 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008797 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008798
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008799 // The ongoing touch should be canceled immediately
8800 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8801 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
8802
8803 // Finger move is ignored
Garfield Tanc734e4f2021-01-15 20:01:39 -08008804 x += 10, y += 10;
8805 processPosition(mapper, x, y);
8806 processSync(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008807 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
Garfield Tanc734e4f2021-01-15 20:01:39 -08008808
8809 // Reactivate display viewport
8810 displayViewport.isActive = true;
8811 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008812 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008813
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008814 // Finger move again starts new gesture
Garfield Tanc734e4f2021-01-15 20:01:39 -08008815 x += 10, y += 10;
8816 processPosition(mapper, x, y);
8817 processSync(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008818 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8819 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008820}
8821
Josh Thielene986aed2023-06-01 14:17:30 +00008822/**
8823 * When the viewport is deactivated (isActive transitions from true to false),
8824 * and touch.enableForInactiveViewport is true, touches prior to the transition
8825 * should not be cancelled.
8826 */
8827TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_TouchesNotAborted) {
8828 addConfigurationProperty("touch.deviceType", "touchScreen");
8829 addConfigurationProperty("touch.enableForInactiveViewport", "1");
8830 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
8831 /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
8832 std::optional<DisplayViewport> optionalDisplayViewport =
8833 mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
8834 ASSERT_TRUE(optionalDisplayViewport.has_value());
8835 DisplayViewport displayViewport = *optionalDisplayViewport;
8836
8837 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8838 prepareAxes(POSITION);
8839 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
8840
8841 // Finger down
8842 int32_t x = 100, y = 100;
8843 processPosition(mapper, x, y);
8844 processSync(mapper);
8845 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8846 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
8847
8848 // Deactivate display viewport
8849 displayViewport.isActive = false;
8850 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
8851 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8852
8853 // The ongoing touch should not be canceled
8854 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
8855
8856 // Finger move is not ignored
8857 x += 10, y += 10;
8858 processPosition(mapper, x, y);
8859 processSync(mapper);
8860 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8861 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
8862
8863 // Reactivate display viewport
8864 displayViewport.isActive = true;
8865 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
8866 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8867
8868 // Finger move continues and does not start new gesture
8869 x += 10, y += 10;
8870 processPosition(mapper, x, y);
8871 processSync(mapper);
8872 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8873 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
8874}
8875
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008876TEST_F(MultiTouchInputMapperTest, VideoFrames_ReceivedByListener) {
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008877 prepareAxes(POSITION);
8878 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008879 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00008880 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008881
8882 NotifyMotionArgs motionArgs;
8883 // Unrotated video frame
8884 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8885 std::vector<TouchVideoFrame> frames{frame};
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008886 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008887 processPosition(mapper, 100, 200);
8888 processSync(mapper);
8889 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8890 ASSERT_EQ(frames, motionArgs.videoFrames);
8891
8892 // Subsequent touch events should not have any videoframes
8893 // This is implemented separately in FakeEventHub,
8894 // but that should match the behaviour of TouchVideoDevice.
8895 processPosition(mapper, 200, 200);
8896 processSync(mapper);
8897 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8898 ASSERT_EQ(std::vector<TouchVideoFrame>(), motionArgs.videoFrames);
8899}
8900
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008901TEST_F(MultiTouchInputMapperTest, VideoFrames_AreNotRotated) {
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008902 prepareAxes(POSITION);
8903 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00008904 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008905 // Unrotated video frame
8906 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8907 NotifyMotionArgs motionArgs;
8908
8909 // Test all 4 orientations
Michael Wrighta9cf4192022-12-01 23:46:39 +00008910 for (ui::Rotation orientation : ftl::enum_range<ui::Rotation>()) {
Harry Cuttsc57cd3c2024-04-24 13:52:55 +00008911 SCOPED_TRACE(StringPrintf("Orientation %s", ftl::enum_string(orientation).c_str()));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008912 clearViewports();
8913 prepareDisplay(orientation);
8914 std::vector<TouchVideoFrame> frames{frame};
8915 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
8916 processPosition(mapper, 100, 200);
8917 processSync(mapper);
8918 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8919 ASSERT_EQ(frames, motionArgs.videoFrames);
8920 }
8921}
8922
8923TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_AreRotated) {
8924 prepareAxes(POSITION);
8925 addConfigurationProperty("touch.deviceType", "touchScreen");
8926 // Since InputReader works in the un-rotated coordinate space, only devices that are not
8927 // orientation-aware are affected by display rotation.
8928 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00008929 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008930 // Unrotated video frame
8931 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8932 NotifyMotionArgs motionArgs;
8933
8934 // Test all 4 orientations
Michael Wrighta9cf4192022-12-01 23:46:39 +00008935 for (ui::Rotation orientation : ftl::enum_range<ui::Rotation>()) {
Harry Cuttsc57cd3c2024-04-24 13:52:55 +00008936 SCOPED_TRACE(StringPrintf("Orientation %s", ftl::enum_string(orientation).c_str()));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008937 clearViewports();
8938 prepareDisplay(orientation);
8939 std::vector<TouchVideoFrame> frames{frame};
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008940 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008941 processPosition(mapper, 100, 200);
8942 processSync(mapper);
8943 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008944 // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction
8945 // compared to the display. This is so that when the window transform (which contains the
8946 // display rotation) is applied later by InputDispatcher, the coordinates end up in the
8947 // window's coordinate space.
8948 frames[0].rotate(getInverseRotation(orientation));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008949 ASSERT_EQ(frames, motionArgs.videoFrames);
lilinnan687e58f2022-07-19 16:00:50 +08008950
8951 // Release finger.
8952 processSync(mapper);
8953 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008954 }
8955}
8956
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008957TEST_F(MultiTouchInputMapperTest, VideoFrames_MultipleFramesAreNotRotated) {
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008958 prepareAxes(POSITION);
8959 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00008960 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008961 // Unrotated video frames. There's no rule that they must all have the same dimensions,
8962 // so mix these.
8963 TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8964 TouchVideoFrame frame2(3, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {1, 3});
8965 TouchVideoFrame frame3(2, 2, {10, 20, 10, 0}, {1, 4});
8966 std::vector<TouchVideoFrame> frames{frame1, frame2, frame3};
8967 NotifyMotionArgs motionArgs;
8968
Michael Wrighta9cf4192022-12-01 23:46:39 +00008969 prepareDisplay(ui::ROTATION_90);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008970 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008971 processPosition(mapper, 100, 200);
8972 processSync(mapper);
8973 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008974 ASSERT_EQ(frames, motionArgs.videoFrames);
8975}
8976
8977TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_MultipleFramesAreRotated) {
8978 prepareAxes(POSITION);
8979 addConfigurationProperty("touch.deviceType", "touchScreen");
8980 // Since InputReader works in the un-rotated coordinate space, only devices that are not
8981 // orientation-aware are affected by display rotation.
8982 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00008983 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008984 // Unrotated video frames. There's no rule that they must all have the same dimensions,
8985 // so mix these.
8986 TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8987 TouchVideoFrame frame2(3, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {1, 3});
8988 TouchVideoFrame frame3(2, 2, {10, 20, 10, 0}, {1, 4});
8989 std::vector<TouchVideoFrame> frames{frame1, frame2, frame3};
8990 NotifyMotionArgs motionArgs;
8991
Michael Wrighta9cf4192022-12-01 23:46:39 +00008992 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008993 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
8994 processPosition(mapper, 100, 200);
8995 processSync(mapper);
8996 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8997 std::for_each(frames.begin(), frames.end(), [](TouchVideoFrame& frame) {
8998 // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction
8999 // compared to the display. This is so that when the window transform (which contains the
9000 // display rotation) is applied later by InputDispatcher, the coordinates end up in the
9001 // window's coordinate space.
Michael Wrighta9cf4192022-12-01 23:46:39 +00009002 frame.rotate(getInverseRotation(ui::ROTATION_90));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07009003 });
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06009004 ASSERT_EQ(frames, motionArgs.videoFrames);
9005}
9006
Arthur Hung9da14732019-09-02 16:16:58 +08009007/**
9008 * If we had defined port associations, but the viewport is not ready, the touch device would be
9009 * expected to be disabled, and it should be enabled after the viewport has found.
9010 */
9011TEST_F(MultiTouchInputMapperTest, Configure_EnabledForAssociatedDisplay) {
Arthur Hung9da14732019-09-02 16:16:58 +08009012 constexpr uint8_t hdmi2 = 1;
9013 const std::string secondaryUniqueId = "uniqueId2";
Michael Wrightfe3de7d2020-07-02 19:05:30 +01009014 constexpr ViewportType type = ViewportType::EXTERNAL;
Arthur Hung9da14732019-09-02 16:16:58 +08009015
9016 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi2);
9017
9018 addConfigurationProperty("touch.deviceType", "touchScreen");
9019 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00009020 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung9da14732019-09-02 16:16:58 +08009021
9022 ASSERT_EQ(mDevice->isEnabled(), false);
9023
9024 // Add display on hdmi2, the device should be enabled and can receive touch event.
9025 prepareSecondaryDisplay(type, hdmi2);
9026 ASSERT_EQ(mDevice->isEnabled(), true);
9027
9028 // Send a touch event.
9029 processPosition(mapper, 100, 100);
9030 processSync(mapper);
9031
9032 NotifyMotionArgs args;
9033 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9034 ASSERT_EQ(SECONDARY_DISPLAY_ID, args.displayId);
9035}
9036
Arthur Hung421eb1c2020-01-16 00:09:42 +08009037TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleSingleTouch) {
Arthur Hung421eb1c2020-01-16 00:09:42 +08009038 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009039 prepareDisplay(ui::ROTATION_0);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009040 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009041 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung421eb1c2020-01-16 00:09:42 +08009042
9043 NotifyMotionArgs motionArgs;
9044
9045 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
9046 // finger down
9047 processId(mapper, 1);
9048 processPosition(mapper, x1, y1);
9049 processSync(mapper);
9050 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9051 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009052 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009053
9054 // finger move
9055 processId(mapper, 1);
9056 processPosition(mapper, x2, y2);
9057 processSync(mapper);
9058 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9059 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009060 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009061
9062 // finger up.
9063 processId(mapper, -1);
9064 processSync(mapper);
9065 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9066 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009067 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009068
9069 // new finger down
9070 processId(mapper, 1);
9071 processPosition(mapper, x3, y3);
9072 processSync(mapper);
9073 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9074 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009075 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009076}
9077
9078/**
arthurhungcc7f9802020-04-30 17:55:40 +08009079 * Test single touch should be canceled when received the MT_TOOL_PALM event, and the following
9080 * MOVE and UP events should be ignored.
Arthur Hung421eb1c2020-01-16 00:09:42 +08009081 */
arthurhungcc7f9802020-04-30 17:55:40 +08009082TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_SinglePointer) {
Arthur Hung421eb1c2020-01-16 00:09:42 +08009083 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009084 prepareDisplay(ui::ROTATION_0);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009085 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009086 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung421eb1c2020-01-16 00:09:42 +08009087
9088 NotifyMotionArgs motionArgs;
9089
9090 // default tool type is finger
9091 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
arthurhungcc7f9802020-04-30 17:55:40 +08009092 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009093 processPosition(mapper, x1, y1);
9094 processSync(mapper);
9095 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9096 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009097 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009098
9099 // Tool changed to MT_TOOL_PALM expect sending the cancel event.
9100 processToolType(mapper, MT_TOOL_PALM);
9101 processSync(mapper);
9102 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9103 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9104
9105 // Ignore the following MOVE and UP events if had detect a palm event.
arthurhungcc7f9802020-04-30 17:55:40 +08009106 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009107 processPosition(mapper, x2, y2);
9108 processSync(mapper);
9109 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9110
9111 // finger up.
arthurhungcc7f9802020-04-30 17:55:40 +08009112 processId(mapper, INVALID_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009113 processSync(mapper);
9114 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9115
9116 // new finger down
arthurhungcc7f9802020-04-30 17:55:40 +08009117 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009118 processToolType(mapper, MT_TOOL_FINGER);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009119 processPosition(mapper, x3, y3);
9120 processSync(mapper);
9121 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9122 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009123 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009124}
9125
arthurhungbf89a482020-04-17 17:37:55 +08009126/**
arthurhungcc7f9802020-04-30 17:55:40 +08009127 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event from some finger,
9128 * and the rest active fingers could still be allowed to receive the events
arthurhungbf89a482020-04-17 17:37:55 +08009129 */
arthurhungcc7f9802020-04-30 17:55:40 +08009130TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_TwoPointers) {
arthurhungbf89a482020-04-17 17:37:55 +08009131 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009132 prepareDisplay(ui::ROTATION_0);
arthurhungbf89a482020-04-17 17:37:55 +08009133 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009134 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungbf89a482020-04-17 17:37:55 +08009135
9136 NotifyMotionArgs motionArgs;
9137
9138 // default tool type is finger
arthurhungcc7f9802020-04-30 17:55:40 +08009139 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220;
9140 processId(mapper, FIRST_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009141 processPosition(mapper, x1, y1);
9142 processSync(mapper);
9143 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9144 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009145 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungbf89a482020-04-17 17:37:55 +08009146
9147 // Second finger down.
arthurhungcc7f9802020-04-30 17:55:40 +08009148 processSlot(mapper, SECOND_SLOT);
9149 processId(mapper, SECOND_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009150 processPosition(mapper, x2, y2);
arthurhungcc7f9802020-04-30 17:55:40 +08009151 processSync(mapper);
9152 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009153 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009154 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009155
9156 // If the tool type of the first finger changes to MT_TOOL_PALM,
9157 // we expect to receive ACTION_POINTER_UP with cancel flag.
9158 processSlot(mapper, FIRST_SLOT);
9159 processId(mapper, FIRST_TRACKING_ID);
9160 processToolType(mapper, MT_TOOL_PALM);
9161 processSync(mapper);
9162 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009163 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009164 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9165
9166 // The following MOVE events of second finger should be processed.
9167 processSlot(mapper, SECOND_SLOT);
9168 processId(mapper, SECOND_TRACKING_ID);
9169 processPosition(mapper, x2 + 1, y2 + 1);
9170 processSync(mapper);
9171 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9172 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009173 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009174
9175 // First finger up. It used to be in palm mode, and we already generated ACTION_POINTER_UP for
9176 // it. Second finger receive move.
9177 processSlot(mapper, FIRST_SLOT);
9178 processId(mapper, INVALID_TRACKING_ID);
9179 processSync(mapper);
9180 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9181 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009182 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009183
9184 // Second finger keeps moving.
9185 processSlot(mapper, SECOND_SLOT);
9186 processId(mapper, SECOND_TRACKING_ID);
9187 processPosition(mapper, x2 + 2, y2 + 2);
9188 processSync(mapper);
9189 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9190 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009191 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009192
9193 // Second finger up.
9194 processId(mapper, INVALID_TRACKING_ID);
9195 processSync(mapper);
9196 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9197 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9198 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9199}
9200
9201/**
9202 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event, if only 1 finger
9203 * is active, it should send CANCEL after receiving the MT_TOOL_PALM event.
9204 */
9205TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_ShouldCancelWhenAllTouchIsPalm) {
9206 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009207 prepareDisplay(ui::ROTATION_0);
arthurhungcc7f9802020-04-30 17:55:40 +08009208 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009209 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungcc7f9802020-04-30 17:55:40 +08009210
9211 NotifyMotionArgs motionArgs;
9212
9213 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
9214 // First finger down.
9215 processId(mapper, FIRST_TRACKING_ID);
9216 processPosition(mapper, x1, y1);
9217 processSync(mapper);
9218 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9219 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009220 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009221
9222 // Second finger down.
9223 processSlot(mapper, SECOND_SLOT);
9224 processId(mapper, SECOND_TRACKING_ID);
9225 processPosition(mapper, x2, y2);
arthurhungbf89a482020-04-17 17:37:55 +08009226 processSync(mapper);
9227 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009228 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009229 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungbf89a482020-04-17 17:37:55 +08009230
arthurhungcc7f9802020-04-30 17:55:40 +08009231 // If the tool type of the first finger changes to MT_TOOL_PALM,
9232 // we expect to receive ACTION_POINTER_UP with cancel flag.
9233 processSlot(mapper, FIRST_SLOT);
9234 processId(mapper, FIRST_TRACKING_ID);
9235 processToolType(mapper, MT_TOOL_PALM);
9236 processSync(mapper);
9237 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009238 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009239 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9240
9241 // Second finger keeps moving.
9242 processSlot(mapper, SECOND_SLOT);
9243 processId(mapper, SECOND_TRACKING_ID);
9244 processPosition(mapper, x2 + 1, y2 + 1);
9245 processSync(mapper);
9246 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9247 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9248
9249 // second finger becomes palm, receive cancel due to only 1 finger is active.
9250 processId(mapper, SECOND_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009251 processToolType(mapper, MT_TOOL_PALM);
9252 processSync(mapper);
9253 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9254 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9255
arthurhungcc7f9802020-04-30 17:55:40 +08009256 // third finger down.
9257 processSlot(mapper, THIRD_SLOT);
9258 processId(mapper, THIRD_TRACKING_ID);
9259 processToolType(mapper, MT_TOOL_FINGER);
arthurhungbf89a482020-04-17 17:37:55 +08009260 processPosition(mapper, x3, y3);
9261 processSync(mapper);
arthurhungbf89a482020-04-17 17:37:55 +08009262 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9263 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009264 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009265 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009266
9267 // third finger move
9268 processId(mapper, THIRD_TRACKING_ID);
9269 processPosition(mapper, x3 + 1, y3 + 1);
9270 processSync(mapper);
9271 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9272 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9273
9274 // first finger up, third finger receive move.
9275 processSlot(mapper, FIRST_SLOT);
9276 processId(mapper, INVALID_TRACKING_ID);
9277 processSync(mapper);
9278 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9279 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009280 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009281
9282 // second finger up, third finger receive move.
9283 processSlot(mapper, SECOND_SLOT);
9284 processId(mapper, INVALID_TRACKING_ID);
9285 processSync(mapper);
9286 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9287 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009288 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009289
9290 // third finger up.
9291 processSlot(mapper, THIRD_SLOT);
9292 processId(mapper, INVALID_TRACKING_ID);
9293 processSync(mapper);
9294 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9295 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9296 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9297}
9298
9299/**
9300 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event from some finger,
9301 * and the active finger could still be allowed to receive the events
9302 */
9303TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_KeepFirstPointer) {
9304 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009305 prepareDisplay(ui::ROTATION_0);
arthurhungcc7f9802020-04-30 17:55:40 +08009306 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009307 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungcc7f9802020-04-30 17:55:40 +08009308
9309 NotifyMotionArgs motionArgs;
9310
9311 // default tool type is finger
9312 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220;
9313 processId(mapper, FIRST_TRACKING_ID);
9314 processPosition(mapper, x1, y1);
9315 processSync(mapper);
9316 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9317 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009318 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009319
9320 // Second finger down.
9321 processSlot(mapper, SECOND_SLOT);
9322 processId(mapper, SECOND_TRACKING_ID);
9323 processPosition(mapper, x2, y2);
9324 processSync(mapper);
9325 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009326 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009327 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009328
9329 // If the tool type of the second finger changes to MT_TOOL_PALM,
9330 // we expect to receive ACTION_POINTER_UP with cancel flag.
9331 processId(mapper, SECOND_TRACKING_ID);
9332 processToolType(mapper, MT_TOOL_PALM);
9333 processSync(mapper);
9334 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009335 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009336 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9337
9338 // The following MOVE event should be processed.
9339 processSlot(mapper, FIRST_SLOT);
9340 processId(mapper, FIRST_TRACKING_ID);
9341 processPosition(mapper, x1 + 1, y1 + 1);
9342 processSync(mapper);
9343 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9344 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009345 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009346
9347 // second finger up.
9348 processSlot(mapper, SECOND_SLOT);
9349 processId(mapper, INVALID_TRACKING_ID);
9350 processSync(mapper);
9351 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9352 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9353
9354 // first finger keep moving
9355 processSlot(mapper, FIRST_SLOT);
9356 processId(mapper, FIRST_TRACKING_ID);
9357 processPosition(mapper, x1 + 2, y1 + 2);
9358 processSync(mapper);
9359 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9360 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9361
9362 // first finger up.
9363 processId(mapper, INVALID_TRACKING_ID);
9364 processSync(mapper);
9365 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9366 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9367 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
arthurhungbf89a482020-04-17 17:37:55 +08009368}
9369
Arthur Hung9ad18942021-06-19 02:04:46 +00009370/**
9371 * Test multi-touch should sent ACTION_POINTER_UP/ACTION_UP when received the INVALID_TRACKING_ID,
9372 * to prevent the driver side may send unexpected data after set tracking id as INVALID_TRACKING_ID
9373 * cause slot be valid again.
9374 */
9375TEST_F(MultiTouchInputMapperTest, Process_MultiTouch_WithInvalidTrackingId) {
9376 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009377 prepareDisplay(ui::ROTATION_0);
Arthur Hung9ad18942021-06-19 02:04:46 +00009378 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009379 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung9ad18942021-06-19 02:04:46 +00009380
9381 NotifyMotionArgs motionArgs;
9382
9383 constexpr int32_t x1 = 100, y1 = 200, x2 = 0, y2 = 0;
9384 // First finger down.
9385 processId(mapper, FIRST_TRACKING_ID);
9386 processPosition(mapper, x1, y1);
9387 processPressure(mapper, RAW_PRESSURE_MAX);
9388 processSync(mapper);
9389 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9390 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009391 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009392
9393 // First finger move.
9394 processId(mapper, FIRST_TRACKING_ID);
9395 processPosition(mapper, x1 + 1, y1 + 1);
9396 processPressure(mapper, RAW_PRESSURE_MAX);
9397 processSync(mapper);
9398 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9399 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009400 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009401
9402 // Second finger down.
9403 processSlot(mapper, SECOND_SLOT);
9404 processId(mapper, SECOND_TRACKING_ID);
9405 processPosition(mapper, x2, y2);
9406 processPressure(mapper, RAW_PRESSURE_MAX);
9407 processSync(mapper);
9408 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009409 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009410 ASSERT_EQ(uint32_t(2), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009411
9412 // second finger up with some unexpected data.
9413 processSlot(mapper, SECOND_SLOT);
9414 processId(mapper, INVALID_TRACKING_ID);
9415 processPosition(mapper, x2, y2);
9416 processSync(mapper);
9417 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009418 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009419 ASSERT_EQ(uint32_t(2), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009420
9421 // first finger up with some unexpected data.
9422 processSlot(mapper, FIRST_SLOT);
9423 processId(mapper, INVALID_TRACKING_ID);
9424 processPosition(mapper, x2, y2);
9425 processPressure(mapper, RAW_PRESSURE_MAX);
9426 processSync(mapper);
9427 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9428 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009429 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009430}
9431
Arpit Singh4b4a4572023-11-24 18:19:56 +00009432TEST_F(MultiTouchInputMapperTest, Reset_RepopulatesMultiTouchState) {
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009433 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009434 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009435 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009436 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009437
9438 // First finger down.
Arpit Singh4b4a4572023-11-24 18:19:56 +00009439 constexpr int32_t x1 = 100, y1 = 200, x2 = 300, y2 = 400;
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009440 processId(mapper, FIRST_TRACKING_ID);
Arpit Singh4b4a4572023-11-24 18:19:56 +00009441 processPosition(mapper, x1, y1);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009442 processPressure(mapper, RAW_PRESSURE_MAX);
9443 processSync(mapper);
9444 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9445 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
9446
9447 // Second finger down.
9448 processSlot(mapper, SECOND_SLOT);
9449 processId(mapper, SECOND_TRACKING_ID);
Arpit Singh4b4a4572023-11-24 18:19:56 +00009450 processPosition(mapper, x2, y2);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009451 processPressure(mapper, RAW_PRESSURE_MAX);
9452 processSync(mapper);
9453 ASSERT_NO_FATAL_FAILURE(
9454 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(ACTION_POINTER_1_DOWN)));
9455
Arpit Singh4b4a4572023-11-24 18:19:56 +00009456 // Set MT Slot state to be repopulated for the required slots
9457 std::vector<int32_t> mtSlotValues(RAW_SLOT_MAX + 1, -1);
9458 mtSlotValues[0] = FIRST_TRACKING_ID;
9459 mtSlotValues[1] = SECOND_TRACKING_ID;
9460 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_TRACKING_ID, mtSlotValues);
9461
9462 mtSlotValues[0] = x1;
9463 mtSlotValues[1] = x2;
9464 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_POSITION_X, mtSlotValues);
9465
9466 mtSlotValues[0] = y1;
9467 mtSlotValues[1] = y2;
9468 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_POSITION_Y, mtSlotValues);
9469
9470 mtSlotValues[0] = RAW_PRESSURE_MAX;
9471 mtSlotValues[1] = RAW_PRESSURE_MAX;
9472 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_PRESSURE, mtSlotValues);
9473
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009474 // Reset the mapper. When the mapper is reset, we expect the current multi-touch state to be
Arpit Singh4b4a4572023-11-24 18:19:56 +00009475 // repopulated. Resetting should cancel the ongoing gesture.
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00009476 resetMapper(mapper, ARBITRARY_TIME);
9477 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9478 WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009479
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009480 // Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
9481 // the existing touch state to generate a down event.
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009482 processPosition(mapper, 301, 302);
9483 processSync(mapper);
9484 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9485 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPressure(1.f))));
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009486 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9487 AllOf(WithMotionAction(ACTION_POINTER_1_DOWN), WithPressure(1.f))));
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009488
9489 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9490}
9491
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009492TEST_F(MultiTouchInputMapperTest, Reset_PreservesLastTouchState_NoPointersDown) {
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009493 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009494 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009495 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009496 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009497
9498 // First finger touches down and releases.
9499 processId(mapper, FIRST_TRACKING_ID);
9500 processPosition(mapper, 100, 200);
9501 processPressure(mapper, RAW_PRESSURE_MAX);
9502 processSync(mapper);
9503 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9504 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
9505 processId(mapper, INVALID_TRACKING_ID);
9506 processSync(mapper);
9507 ASSERT_NO_FATAL_FAILURE(
9508 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
9509
9510 // Reset the mapper. When the mapper is reset, we expect it to restore the latest
9511 // raw state where no pointers are down.
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00009512 resetMapper(mapper, ARBITRARY_TIME);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009513 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9514
9515 // Send an empty sync frame. Since there are no pointers, no events are generated.
9516 processSync(mapper);
9517 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9518}
9519
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009520TEST_F(MultiTouchInputMapperTest, StylusSourceIsAddedDynamicallyFromToolType) {
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009521 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009522 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009523 prepareAxes(POSITION | ID | SLOT | PRESSURE | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009524 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009525 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009526
9527 // Even if the device supports reporting the ABS_MT_TOOL_TYPE axis, which could give it the
9528 // ability to report MT_TOOL_PEN, we do not report the device as coming from a stylus source.
9529 // Due to limitations in the evdev protocol, we cannot say for certain that a device is capable
9530 // of reporting stylus events just because it supports ABS_MT_TOOL_TYPE.
9531 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
9532
9533 // However, if the device ever ends up reporting an event with MT_TOOL_PEN, it should be
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009534 // reported with the stylus source.
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009535 processId(mapper, FIRST_TRACKING_ID);
9536 processToolType(mapper, MT_TOOL_PEN);
9537 processPosition(mapper, 100, 200);
9538 processPressure(mapper, RAW_PRESSURE_MAX);
9539 processSync(mapper);
9540 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9541 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
9542 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009543 WithToolType(ToolType::STYLUS))));
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009544
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009545 // Now that we know the device supports styluses, ensure that the device is re-configured with
9546 // the stylus source.
9547 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, mapper.getSources());
9548 {
9549 const auto& devices = mReader->getInputDevices();
9550 auto deviceInfo =
9551 std::find_if(devices.begin(), devices.end(),
9552 [](const InputDeviceInfo& info) { return info.getId() == DEVICE_ID; });
9553 LOG_ALWAYS_FATAL_IF(deviceInfo == devices.end(), "Cannot find InputDevice");
9554 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, deviceInfo->getSources());
9555 }
9556
9557 // Ensure the device was not reset to prevent interruptions of any ongoing gestures.
9558 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
9559
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009560 processId(mapper, INVALID_TRACKING_ID);
9561 processSync(mapper);
9562 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9563 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
9564 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009565 WithToolType(ToolType::STYLUS))));
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009566}
9567
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009568// --- MultiTouchInputMapperTest_ExternalDevice ---
9569
9570class MultiTouchInputMapperTest_ExternalDevice : public MultiTouchInputMapperTest {
9571protected:
Chris Yea52ade12020-08-27 16:49:20 -07009572 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL); }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009573};
9574
9575/**
9576 * Expect fallback to internal viewport if device is external and external viewport is not present.
9577 */
9578TEST_F(MultiTouchInputMapperTest_ExternalDevice, Viewports_Fallback) {
9579 prepareAxes(POSITION);
9580 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009581 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00009582 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009583
9584 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
9585
9586 NotifyMotionArgs motionArgs;
9587
9588 // Expect the event to be sent to the internal viewport,
9589 // because an external viewport is not present.
9590 processPosition(mapper, 100, 100);
9591 processSync(mapper);
9592 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009593 ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, motionArgs.displayId);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009594
9595 // Expect the event to be sent to the external viewport if it is present.
Michael Wrightfe3de7d2020-07-02 19:05:30 +01009596 prepareSecondaryDisplay(ViewportType::EXTERNAL);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009597 processPosition(mapper, 100, 100);
9598 processSync(mapper);
9599 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9600 ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
9601}
Arthur Hung4197f6b2020-03-16 15:39:59 +08009602
Prabir Pradhan3ed7e352024-05-03 23:59:43 +00009603// TODO(b/281840344): Remove the test when the old touchpad stack is removed. It is currently
9604// unclear what the behavior of the touchpad logic in TouchInputMapper should do after the
9605// PointerChoreographer refactor.
9606TEST_F(MultiTouchInputMapperTest, DISABLED_Process_TouchpadPointer) {
Harry Cutts8722be92024-04-05 14:46:05 +00009607 // prepare device
Michael Wrighta9cf4192022-12-01 23:46:39 +00009608 prepareDisplay(ui::ROTATION_0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009609 prepareAxes(POSITION | ID | SLOT);
9610 mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
9611 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00009612 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009613 // run uncaptured pointer tests - pushes out generic events
9614 // FINGER 0 DOWN
9615 processId(mapper, 3);
9616 processPosition(mapper, 100, 100);
9617 processKey(mapper, BTN_TOUCH, 1);
9618 processSync(mapper);
9619
9620 // start at (100,100), cursor should be at (0,0) * scale
9621 NotifyMotionArgs args;
9622 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9623 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
9624 ASSERT_NO_FATAL_FAILURE(
9625 assertPointerCoords(args.pointerCoords[0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
9626
9627 // FINGER 0 MOVE
9628 processPosition(mapper, 200, 200);
9629 processSync(mapper);
9630
9631 // compute scaling to help with touch position checking
9632 float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
9633 float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
9634 float scale =
9635 mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
9636
9637 // translate from (100,100) -> (200,200), cursor should have changed to (100,100) * scale)
9638 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9639 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
9640 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], 100 * scale, 100 * scale, 0,
9641 0, 0, 0, 0, 0, 0, 0));
LiZhihong758eb562022-11-03 15:28:29 +08009642
9643 // BUTTON DOWN
9644 processKey(mapper, BTN_LEFT, 1);
9645 processSync(mapper);
9646
9647 // touchinputmapper design sends a move before button press
9648 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9649 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
9650 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9651 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, args.action);
9652
9653 // BUTTON UP
9654 processKey(mapper, BTN_LEFT, 0);
9655 processSync(mapper);
9656
9657 // touchinputmapper design sends a move after button release
9658 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9659 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, args.action);
9660 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9661 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009662}
9663
Harry Cutts8722be92024-04-05 14:46:05 +00009664TEST_F(MultiTouchInputMapperTest, Touchpad_GetSources) {
Michael Wrighta9cf4192022-12-01 23:46:39 +00009665 prepareDisplay(ui::ROTATION_0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009666 prepareAxes(POSITION | ID | SLOT);
9667 mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
Hiroki Sato25040232024-02-22 17:21:22 +09009668 mFakePolicy->setPointerCapture(/*window=*/nullptr);
Arpit Singha8c236b2023-04-25 13:56:05 +00009669 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009670
Josep del Río2d8c79a2023-01-23 19:33:50 +00009671 // uncaptured touchpad should be a pointer device
9672 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009673}
9674
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009675// --- BluetoothMultiTouchInputMapperTest ---
9676
9677class BluetoothMultiTouchInputMapperTest : public MultiTouchInputMapperTest {
9678protected:
9679 void SetUp() override {
9680 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL, BUS_BLUETOOTH);
9681 }
9682};
9683
9684TEST_F(BluetoothMultiTouchInputMapperTest, TimestampSmoothening) {
9685 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009686 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009687 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009688 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009689
9690 nsecs_t kernelEventTime = ARBITRARY_TIME;
9691 nsecs_t expectedEventTime = ARBITRARY_TIME;
9692 // Touch down.
9693 processId(mapper, FIRST_TRACKING_ID);
9694 processPosition(mapper, 100, 200);
9695 processPressure(mapper, RAW_PRESSURE_MAX);
9696 processSync(mapper, ARBITRARY_TIME);
9697 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9698 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithEventTime(ARBITRARY_TIME))));
9699
9700 // Process several events that come in quick succession, according to their timestamps.
9701 for (int i = 0; i < 3; i++) {
9702 constexpr static nsecs_t delta = ms2ns(1);
9703 static_assert(delta < MIN_BLUETOOTH_TIMESTAMP_DELTA);
9704 kernelEventTime += delta;
9705 expectedEventTime += MIN_BLUETOOTH_TIMESTAMP_DELTA;
9706
9707 processPosition(mapper, 101 + i, 201 + i);
9708 processSync(mapper, kernelEventTime);
9709 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9710 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
9711 WithEventTime(expectedEventTime))));
9712 }
9713
9714 // Release the touch.
9715 processId(mapper, INVALID_TRACKING_ID);
9716 processPressure(mapper, RAW_PRESSURE_MIN);
9717 processSync(mapper, ARBITRARY_TIME + ms2ns(50));
9718 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9719 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
9720 WithEventTime(ARBITRARY_TIME + ms2ns(50)))));
9721}
9722
9723// --- MultiTouchPointerModeTest ---
9724
HQ Liue6983c72022-04-19 22:14:56 +00009725class MultiTouchPointerModeTest : public MultiTouchInputMapperTest {
9726protected:
9727 float mPointerMovementScale;
9728 float mPointerXZoomScale;
9729 void preparePointerMode(int xAxisResolution, int yAxisResolution) {
9730 addConfigurationProperty("touch.deviceType", "pointer");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009731 prepareDisplay(ui::ROTATION_0);
HQ Liue6983c72022-04-19 22:14:56 +00009732
9733 prepareAxes(POSITION);
9734 prepareAbsoluteAxisResolution(xAxisResolution, yAxisResolution);
9735 // In order to enable swipe and freeform gesture in pointer mode, pointer capture
9736 // needs to be disabled, and the pointer gesture needs to be enabled.
Hiroki Sato25040232024-02-22 17:21:22 +09009737 mFakePolicy->setPointerCapture(/*window=*/nullptr);
HQ Liue6983c72022-04-19 22:14:56 +00009738 mFakePolicy->setPointerGestureEnabled(true);
HQ Liue6983c72022-04-19 22:14:56 +00009739
9740 float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
9741 float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
9742 mPointerMovementScale =
9743 mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
9744 mPointerXZoomScale =
9745 mFakePolicy->getPointerGestureZoomSpeedRatio() * displayDiagonal / rawDiagonal;
9746 }
9747
9748 void prepareAbsoluteAxisResolution(int xAxisResolution, int yAxisResolution) {
9749 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX,
9750 /*flat*/ 0,
9751 /*fuzz*/ 0, /*resolution*/ xAxisResolution);
9752 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX,
9753 /*flat*/ 0,
9754 /*fuzz*/ 0, /*resolution*/ yAxisResolution);
9755 }
9756};
9757
9758/**
9759 * Two fingers down on a pointer mode touch pad. The width
9760 * of the two finger is larger than 1/4 of the touch pack diagnal length. However, it
9761 * is smaller than the fixed min physical length 30mm. Two fingers' distance must
9762 * be greater than the both value to be freeform gesture, so that after two
9763 * fingers start to move downwards, the gesture should be swipe.
9764 */
9765TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthSwipe) {
9766 // The min freeform gesture width is 25units/mm x 30mm = 750
9767 // which is greater than fraction of the diagnal length of the touchpad (349).
9768 // Thus, MaxSwipWidth is 750.
Harry Cutts33476232023-01-30 19:57:29 +00009769 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +00009770 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009771 NotifyMotionArgs motionArgs;
9772
9773 // Two fingers down at once.
9774 // The two fingers are 450 units apart, expects the current gesture to be PRESS
9775 // Pointer's initial position is used the [0,0] coordinate.
9776 int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125;
9777
9778 processId(mapper, FIRST_TRACKING_ID);
9779 processPosition(mapper, x1, y1);
9780 processMTSync(mapper);
9781 processId(mapper, SECOND_TRACKING_ID);
9782 processPosition(mapper, x2, y2);
9783 processMTSync(mapper);
9784 processSync(mapper);
9785
9786 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009787 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009788 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009789 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009790 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009791 ASSERT_NO_FATAL_FAILURE(
9792 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9793
9794 // It should be recognized as a SWIPE gesture when two fingers start to move down,
9795 // that there should be 1 pointer.
9796 int32_t movingDistance = 200;
9797 y1 += movingDistance;
9798 y2 += movingDistance;
9799
9800 processId(mapper, FIRST_TRACKING_ID);
9801 processPosition(mapper, x1, y1);
9802 processMTSync(mapper);
9803 processId(mapper, SECOND_TRACKING_ID);
9804 processPosition(mapper, x2, y2);
9805 processMTSync(mapper);
9806 processSync(mapper);
9807
9808 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009809 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009810 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009811 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009812 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009813 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
9814 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9815 0, 0, 0, 0));
9816}
9817
9818/**
9819 * Two fingers down on a pointer mode touch pad. The width of the two finger is larger
9820 * than the minimum freeform gesture width, 30mm. However, it is smaller than 1/4 of
9821 * the touch pack diagnal length. Two fingers' distance must be greater than the both
9822 * value to be freeform gesture, so that after two fingers start to move downwards,
9823 * the gesture should be swipe.
9824 */
9825TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthLowResolutionSwipe) {
9826 // The min freeform gesture width is 5units/mm x 30mm = 150
9827 // which is greater than fraction of the diagnal length of the touchpad (349).
9828 // Thus, MaxSwipWidth is the fraction of the diagnal length, 349.
Harry Cutts33476232023-01-30 19:57:29 +00009829 preparePointerMode(/*xResolution=*/5, /*yResolution=*/5);
Arpit Singha8c236b2023-04-25 13:56:05 +00009830 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009831 NotifyMotionArgs motionArgs;
9832
9833 // Two fingers down at once.
9834 // The two fingers are 250 units apart, expects the current gesture to be PRESS
9835 // Pointer's initial position is used the [0,0] coordinate.
9836 int32_t x1 = 100, y1 = 125, x2 = 350, y2 = 125;
9837
9838 processId(mapper, FIRST_TRACKING_ID);
9839 processPosition(mapper, x1, y1);
9840 processMTSync(mapper);
9841 processId(mapper, SECOND_TRACKING_ID);
9842 processPosition(mapper, x2, y2);
9843 processMTSync(mapper);
9844 processSync(mapper);
9845
9846 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009847 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009848 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009849 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009850 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009851 ASSERT_NO_FATAL_FAILURE(
9852 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9853
9854 // It should be recognized as a SWIPE gesture when two fingers start to move down,
9855 // and there should be 1 pointer.
9856 int32_t movingDistance = 200;
9857 y1 += movingDistance;
9858 y2 += movingDistance;
9859
9860 processId(mapper, FIRST_TRACKING_ID);
9861 processPosition(mapper, x1, y1);
9862 processMTSync(mapper);
9863 processId(mapper, SECOND_TRACKING_ID);
9864 processPosition(mapper, x2, y2);
9865 processMTSync(mapper);
9866 processSync(mapper);
9867
9868 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009869 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009870 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009871 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009872 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009873 // New coordinate is the scaled relative coordinate from the initial coordinate.
9874 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
9875 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9876 0, 0, 0, 0));
9877}
9878
9879/**
9880 * Touch the touch pad with two fingers with a distance wider than the minimum freeform
9881 * gesture width and 1/4 of the diagnal length of the touchpad. Expect to receive
9882 * freeform gestures after two fingers start to move downwards.
9883 */
9884TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthFreeform) {
Harry Cutts33476232023-01-30 19:57:29 +00009885 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +00009886 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009887
9888 NotifyMotionArgs motionArgs;
9889
9890 // Two fingers down at once. Wider than the max swipe width.
9891 // The gesture is expected to be PRESS, then transformed to FREEFORM
9892 int32_t x1 = 100, y1 = 125, x2 = 900, y2 = 125;
9893
9894 processId(mapper, FIRST_TRACKING_ID);
9895 processPosition(mapper, x1, y1);
9896 processMTSync(mapper);
9897 processId(mapper, SECOND_TRACKING_ID);
9898 processPosition(mapper, x2, y2);
9899 processMTSync(mapper);
9900 processSync(mapper);
9901
9902 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009903 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009904 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009905 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009906 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009907 // One pointer for PRESS, and its coordinate is used as the origin for pointer coordinates.
9908 ASSERT_NO_FATAL_FAILURE(
9909 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9910
9911 int32_t movingDistance = 200;
9912
9913 // Move two fingers down, expect a cancel event because gesture is changing to freeform,
9914 // then two down events for two pointers.
9915 y1 += movingDistance;
9916 y2 += movingDistance;
9917
9918 processId(mapper, FIRST_TRACKING_ID);
9919 processPosition(mapper, x1, y1);
9920 processMTSync(mapper);
9921 processId(mapper, SECOND_TRACKING_ID);
9922 processPosition(mapper, x2, y2);
9923 processMTSync(mapper);
9924 processSync(mapper);
9925
9926 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9927 // The previous PRESS gesture is cancelled, because it is transformed to freeform
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009928 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009929 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9930 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009931 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009932 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009933 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
9934 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009935 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009936 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009937 ASSERT_EQ(2U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009938 ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN, motionArgs.action & AMOTION_EVENT_ACTION_MASK);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009939 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009940 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009941 // Two pointers' scaled relative coordinates from their initial centroid.
9942 // Initial y coordinates are 0 as y1 and y2 have the same value.
9943 float cookedX1 = (x1 - x2) / 2 * mPointerXZoomScale;
9944 float cookedX2 = (x2 - x1) / 2 * mPointerXZoomScale;
9945 // When pointers move, the new coordinates equal to the initial coordinates plus
9946 // scaled moving distance.
9947 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
9948 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9949 0, 0, 0, 0));
9950 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], cookedX2,
9951 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9952 0, 0, 0, 0));
9953
9954 // Move two fingers down again, expect one MOVE motion event.
9955 y1 += movingDistance;
9956 y2 += movingDistance;
9957
9958 processId(mapper, FIRST_TRACKING_ID);
9959 processPosition(mapper, x1, y1);
9960 processMTSync(mapper);
9961 processId(mapper, SECOND_TRACKING_ID);
9962 processPosition(mapper, x2, y2);
9963 processMTSync(mapper);
9964 processSync(mapper);
9965
9966 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009967 ASSERT_EQ(2U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009968 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009969 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009970 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009971 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
9972 movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
9973 0, 0, 0, 0, 0));
9974 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], cookedX2,
9975 movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
9976 0, 0, 0, 0, 0));
9977}
9978
Harry Cutts39b7ca22022-10-05 15:55:48 +00009979TEST_F(MultiTouchPointerModeTest, TwoFingerSwipeOffsets) {
Harry Cutts33476232023-01-30 19:57:29 +00009980 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +00009981 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Harry Cutts39b7ca22022-10-05 15:55:48 +00009982 NotifyMotionArgs motionArgs;
9983
9984 // Place two fingers down.
9985 int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125;
9986
9987 processId(mapper, FIRST_TRACKING_ID);
9988 processPosition(mapper, x1, y1);
9989 processMTSync(mapper);
9990 processId(mapper, SECOND_TRACKING_ID);
9991 processPosition(mapper, x2, y2);
9992 processMTSync(mapper);
9993 processSync(mapper);
9994
9995 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009996 ASSERT_EQ(1U, motionArgs.getPointerCount());
Harry Cutts39b7ca22022-10-05 15:55:48 +00009997 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
9998 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
9999 ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET));
10000 ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET));
10001
10002 // Move the two fingers down and to the left.
10003 int32_t movingDistance = 200;
10004 x1 -= movingDistance;
10005 y1 += movingDistance;
10006 x2 -= movingDistance;
10007 y2 += movingDistance;
10008
10009 processId(mapper, FIRST_TRACKING_ID);
10010 processPosition(mapper, x1, y1);
10011 processMTSync(mapper);
10012 processId(mapper, SECOND_TRACKING_ID);
10013 processPosition(mapper, x2, y2);
10014 processMTSync(mapper);
10015 processSync(mapper);
10016
10017 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010018 ASSERT_EQ(1U, motionArgs.getPointerCount());
Harry Cutts39b7ca22022-10-05 15:55:48 +000010019 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
10020 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
10021 ASSERT_LT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET), 0);
10022 ASSERT_GT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET), 0);
10023}
10024
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010025TEST_F(MultiTouchPointerModeTest, WhenViewportActiveStatusChanged_PointerGestureIsReset) {
Harry Cutts33476232023-01-30 19:57:29 +000010026 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010027 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +000010028 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010029 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
10030
10031 // Start a stylus gesture.
10032 processKey(mapper, BTN_TOOL_PEN, 1);
10033 processId(mapper, FIRST_TRACKING_ID);
10034 processPosition(mapper, 100, 200);
10035 processSync(mapper);
10036 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10037 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
10038 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010039 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010040 // TODO(b/257078296): Pointer mode generates extra event.
10041 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10042 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
10043 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010044 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010045 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
10046
10047 // Make the viewport inactive. This will put the device in disabled mode, and the ongoing stylus
10048 // gesture should be disabled.
10049 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
10050 viewport->isActive = false;
10051 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +000010052 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010053 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10054 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
10055 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010056 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010057 // TODO(b/257078296): Pointer mode generates extra event.
10058 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10059 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
10060 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010061 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010062 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
10063}
10064
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010065// --- PeripheralControllerTest ---
Chris Yee2b1e5c2021-03-10 22:45:12 -080010066
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010067class PeripheralControllerTest : public testing::Test {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010068protected:
10069 static const char* DEVICE_NAME;
10070 static const char* DEVICE_LOCATION;
10071 static const int32_t DEVICE_ID;
10072 static const int32_t DEVICE_GENERATION;
10073 static const int32_t DEVICE_CONTROLLER_NUMBER;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010074 static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010075 static const int32_t EVENTHUB_ID;
10076
10077 std::shared_ptr<FakeEventHub> mFakeEventHub;
10078 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010079 std::unique_ptr<TestInputListener> mFakeListener;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010080 std::unique_ptr<InstrumentedInputReader> mReader;
10081 std::shared_ptr<InputDevice> mDevice;
10082
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010083 virtual void SetUp(ftl::Flags<InputDeviceClass> classes) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010084 mFakeEventHub = std::make_unique<FakeEventHub>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010085 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010086 mFakeListener = std::make_unique<TestInputListener>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010087 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010088 *mFakeListener);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010089 mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes);
10090 }
10091
10092 void SetUp() override { SetUp(DEVICE_CLASSES); }
10093
10094 void TearDown() override {
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010095 mFakeListener.reset();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010096 mFakePolicy.clear();
10097 }
10098
Chris Yee2b1e5c2021-03-10 22:45:12 -080010099 std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
10100 const std::string& location, int32_t eventHubId,
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010101 ftl::Flags<InputDeviceClass> classes) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010102 InputDeviceIdentifier identifier;
10103 identifier.name = name;
10104 identifier.location = location;
10105 std::shared_ptr<InputDevice> device =
10106 std::make_shared<InputDevice>(mReader->getContext(), deviceId, DEVICE_GENERATION,
10107 identifier);
10108 mReader->pushNextDevice(device);
10109 mFakeEventHub->addDevice(eventHubId, name, classes);
10110 mReader->loopOnce();
10111 return device;
10112 }
10113
10114 template <class T, typename... Args>
10115 T& addControllerAndConfigure(Args... args) {
10116 T& controller = mDevice->addController<T>(EVENTHUB_ID, args...);
10117
10118 return controller;
10119 }
10120};
10121
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010122const char* PeripheralControllerTest::DEVICE_NAME = "device";
10123const char* PeripheralControllerTest::DEVICE_LOCATION = "BLUETOOTH";
10124const int32_t PeripheralControllerTest::DEVICE_ID = END_RESERVED_ID + 1000;
10125const int32_t PeripheralControllerTest::DEVICE_GENERATION = 2;
10126const int32_t PeripheralControllerTest::DEVICE_CONTROLLER_NUMBER = 0;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010127const ftl::Flags<InputDeviceClass> PeripheralControllerTest::DEVICE_CLASSES =
10128 ftl::Flags<InputDeviceClass>(0); // not needed for current tests
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010129const int32_t PeripheralControllerTest::EVENTHUB_ID = 1;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010130
10131// --- BatteryControllerTest ---
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010132class BatteryControllerTest : public PeripheralControllerTest {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010133protected:
10134 void SetUp() override {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010135 PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::BATTERY);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010136 }
10137};
10138
10139TEST_F(BatteryControllerTest, GetBatteryCapacity) {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010140 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010141
Harry Cuttsa5b71292022-11-28 12:56:17 +000010142 ASSERT_TRUE(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY));
10143 ASSERT_EQ(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY).value_or(-1),
10144 FakeEventHub::BATTERY_CAPACITY);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010145}
10146
10147TEST_F(BatteryControllerTest, GetBatteryStatus) {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010148 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010149
Harry Cuttsa5b71292022-11-28 12:56:17 +000010150 ASSERT_TRUE(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY));
10151 ASSERT_EQ(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY).value_or(-1),
10152 FakeEventHub::BATTERY_STATUS);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010153}
10154
10155// --- LightControllerTest ---
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010156class LightControllerTest : public PeripheralControllerTest {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010157protected:
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010158 void SetUp() override {
10159 PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::LIGHT);
10160 }
Chris Yee2b1e5c2021-03-10 22:45:12 -080010161};
10162
Chris Ye85758332021-05-16 23:05:17 -070010163TEST_F(LightControllerTest, MonoLight) {
10164 RawLightInfo infoMono = {.id = 1,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010165 .name = "mono_light",
Chris Ye85758332021-05-16 23:05:17 -070010166 .maxBrightness = 255,
10167 .flags = InputLightClass::BRIGHTNESS,
10168 .path = ""};
10169 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010170
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010171 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010172 InputDeviceInfo info;
10173 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010174 std::vector<InputDeviceLightInfo> lights = info.getLights();
10175 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010176 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10177 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10178
10179 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_BRIGHTNESS));
10180 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_BRIGHTNESS);
10181}
10182
DingYong99f2c3c2023-12-20 15:46:06 +080010183TEST_F(LightControllerTest, MonoKeyboardMuteLight) {
10184 RawLightInfo infoMono = {.id = 1,
10185 .name = "mono_keyboard_mute",
10186 .maxBrightness = 255,
10187 .flags = InputLightClass::BRIGHTNESS |
10188 InputLightClass::KEYBOARD_MIC_MUTE,
10189 .path = ""};
10190 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10191
10192 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10193 std::list<NotifyArgs> unused =
10194 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10195 /*changes=*/{});
10196
10197 InputDeviceInfo info;
10198 controller.populateDeviceInfo(&info);
10199 std::vector<InputDeviceLightInfo> lights = info.getLights();
10200 ASSERT_EQ(1U, lights.size());
10201 ASSERT_EQ(InputDeviceLightType::KEYBOARD_MIC_MUTE, lights[0].type);
10202 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10203}
10204
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010205TEST_F(LightControllerTest, MonoKeyboardBacklight) {
10206 RawLightInfo infoMono = {.id = 1,
10207 .name = "mono_keyboard_backlight",
10208 .maxBrightness = 255,
10209 .flags = InputLightClass::BRIGHTNESS |
10210 InputLightClass::KEYBOARD_BACKLIGHT,
10211 .path = ""};
10212 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10213
10214 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10215 InputDeviceInfo info;
10216 controller.populateDeviceInfo(&info);
10217 std::vector<InputDeviceLightInfo> lights = info.getLights();
10218 ASSERT_EQ(1U, lights.size());
10219 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10220 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010221
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010222 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_BRIGHTNESS));
10223 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_BRIGHTNESS);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010224}
10225
Vaibhav Devmurari16c24192023-05-04 15:20:12 +000010226TEST_F(LightControllerTest, Ignore_MonoLight_WithPreferredBacklightLevels) {
10227 RawLightInfo infoMono = {.id = 1,
10228 .name = "mono_light",
10229 .maxBrightness = 255,
10230 .flags = InputLightClass::BRIGHTNESS,
10231 .path = ""};
10232 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10233 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10234 "0,100,200");
10235
10236 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10237 std::list<NotifyArgs> unused =
10238 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10239 /*changes=*/{});
10240
10241 InputDeviceInfo info;
10242 controller.populateDeviceInfo(&info);
10243 std::vector<InputDeviceLightInfo> lights = info.getLights();
10244 ASSERT_EQ(1U, lights.size());
10245 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10246}
10247
10248TEST_F(LightControllerTest, KeyboardBacklight_WithNoPreferredBacklightLevels) {
10249 RawLightInfo infoMono = {.id = 1,
10250 .name = "mono_keyboard_backlight",
10251 .maxBrightness = 255,
10252 .flags = InputLightClass::BRIGHTNESS |
10253 InputLightClass::KEYBOARD_BACKLIGHT,
10254 .path = ""};
10255 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10256
10257 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10258 std::list<NotifyArgs> unused =
10259 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10260 /*changes=*/{});
10261
10262 InputDeviceInfo info;
10263 controller.populateDeviceInfo(&info);
10264 std::vector<InputDeviceLightInfo> lights = info.getLights();
10265 ASSERT_EQ(1U, lights.size());
10266 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10267}
10268
10269TEST_F(LightControllerTest, KeyboardBacklight_WithPreferredBacklightLevels) {
10270 RawLightInfo infoMono = {.id = 1,
10271 .name = "mono_keyboard_backlight",
10272 .maxBrightness = 255,
10273 .flags = InputLightClass::BRIGHTNESS |
10274 InputLightClass::KEYBOARD_BACKLIGHT,
10275 .path = ""};
10276 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10277 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10278 "0,100,200");
10279
10280 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10281 std::list<NotifyArgs> unused =
10282 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10283 /*changes=*/{});
10284
10285 InputDeviceInfo info;
10286 controller.populateDeviceInfo(&info);
10287 std::vector<InputDeviceLightInfo> lights = info.getLights();
10288 ASSERT_EQ(1U, lights.size());
10289 ASSERT_EQ(3U, lights[0].preferredBrightnessLevels.size());
10290 std::set<BrightnessLevel>::iterator it = lights[0].preferredBrightnessLevels.begin();
10291 ASSERT_EQ(BrightnessLevel(0), *it);
10292 std::advance(it, 1);
10293 ASSERT_EQ(BrightnessLevel(100), *it);
10294 std::advance(it, 1);
10295 ASSERT_EQ(BrightnessLevel(200), *it);
10296}
10297
10298TEST_F(LightControllerTest, KeyboardBacklight_WithWrongPreferredBacklightLevels) {
10299 RawLightInfo infoMono = {.id = 1,
10300 .name = "mono_keyboard_backlight",
10301 .maxBrightness = 255,
10302 .flags = InputLightClass::BRIGHTNESS |
10303 InputLightClass::KEYBOARD_BACKLIGHT,
10304 .path = ""};
10305 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10306 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10307 "0,100,200,300,400,500");
10308
10309 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10310 std::list<NotifyArgs> unused =
10311 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10312 /*changes=*/{});
10313
10314 InputDeviceInfo info;
10315 controller.populateDeviceInfo(&info);
10316 std::vector<InputDeviceLightInfo> lights = info.getLights();
10317 ASSERT_EQ(1U, lights.size());
10318 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10319}
10320
Chris Yee2b1e5c2021-03-10 22:45:12 -080010321TEST_F(LightControllerTest, RGBLight) {
10322 RawLightInfo infoRed = {.id = 1,
10323 .name = "red",
10324 .maxBrightness = 255,
10325 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED,
10326 .path = ""};
10327 RawLightInfo infoGreen = {.id = 2,
10328 .name = "green",
10329 .maxBrightness = 255,
10330 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN,
10331 .path = ""};
10332 RawLightInfo infoBlue = {.id = 3,
10333 .name = "blue",
10334 .maxBrightness = 255,
10335 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE,
10336 .path = ""};
10337 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10338 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10339 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10340
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010341 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010342 InputDeviceInfo info;
10343 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010344 std::vector<InputDeviceLightInfo> lights = info.getLights();
10345 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010346 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10347 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10348 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10349
10350 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10351 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10352}
10353
10354TEST_F(LightControllerTest, CorrectRGBKeyboardBacklight) {
10355 RawLightInfo infoRed = {.id = 1,
10356 .name = "red_keyboard_backlight",
10357 .maxBrightness = 255,
10358 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED |
10359 InputLightClass::KEYBOARD_BACKLIGHT,
10360 .path = ""};
10361 RawLightInfo infoGreen = {.id = 2,
10362 .name = "green_keyboard_backlight",
10363 .maxBrightness = 255,
10364 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN |
10365 InputLightClass::KEYBOARD_BACKLIGHT,
10366 .path = ""};
10367 RawLightInfo infoBlue = {.id = 3,
10368 .name = "blue_keyboard_backlight",
10369 .maxBrightness = 255,
10370 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE |
10371 InputLightClass::KEYBOARD_BACKLIGHT,
10372 .path = ""};
10373 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10374 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10375 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10376
10377 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10378 InputDeviceInfo info;
10379 controller.populateDeviceInfo(&info);
10380 std::vector<InputDeviceLightInfo> lights = info.getLights();
10381 ASSERT_EQ(1U, lights.size());
10382 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10383 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10384 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10385
10386 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10387 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10388}
10389
10390TEST_F(LightControllerTest, IncorrectRGBKeyboardBacklight) {
10391 RawLightInfo infoRed = {.id = 1,
10392 .name = "red",
10393 .maxBrightness = 255,
10394 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED,
10395 .path = ""};
10396 RawLightInfo infoGreen = {.id = 2,
10397 .name = "green",
10398 .maxBrightness = 255,
10399 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN,
10400 .path = ""};
10401 RawLightInfo infoBlue = {.id = 3,
10402 .name = "blue",
10403 .maxBrightness = 255,
10404 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE,
10405 .path = ""};
10406 RawLightInfo infoGlobal = {.id = 3,
10407 .name = "global_keyboard_backlight",
10408 .maxBrightness = 255,
10409 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GLOBAL |
10410 InputLightClass::KEYBOARD_BACKLIGHT,
10411 .path = ""};
10412 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10413 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10414 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10415 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoGlobal));
10416
10417 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10418 InputDeviceInfo info;
10419 controller.populateDeviceInfo(&info);
10420 std::vector<InputDeviceLightInfo> lights = info.getLights();
10421 ASSERT_EQ(1U, lights.size());
10422 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10423 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10424 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010425
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010426 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10427 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010428}
10429
10430TEST_F(LightControllerTest, MultiColorRGBLight) {
10431 RawLightInfo infoColor = {.id = 1,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010432 .name = "multi_color",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010433 .maxBrightness = 255,
10434 .flags = InputLightClass::BRIGHTNESS |
10435 InputLightClass::MULTI_INTENSITY |
10436 InputLightClass::MULTI_INDEX,
10437 .path = ""};
10438
10439 mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
10440
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010441 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010442 InputDeviceInfo info;
10443 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010444 std::vector<InputDeviceLightInfo> lights = info.getLights();
10445 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010446 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10447 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10448 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10449
10450 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10451 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10452}
10453
10454TEST_F(LightControllerTest, MultiColorRGBKeyboardBacklight) {
10455 RawLightInfo infoColor = {.id = 1,
10456 .name = "multi_color_keyboard_backlight",
10457 .maxBrightness = 255,
10458 .flags = InputLightClass::BRIGHTNESS |
10459 InputLightClass::MULTI_INTENSITY |
10460 InputLightClass::MULTI_INDEX |
10461 InputLightClass::KEYBOARD_BACKLIGHT,
10462 .path = ""};
10463
10464 mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
10465
10466 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10467 InputDeviceInfo info;
10468 controller.populateDeviceInfo(&info);
10469 std::vector<InputDeviceLightInfo> lights = info.getLights();
10470 ASSERT_EQ(1U, lights.size());
10471 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10472 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10473 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010474
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010475 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10476 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010477}
10478
Josep del Rioa1046a82023-08-24 19:57:27 +000010479TEST_F(LightControllerTest, SonyPlayerIdLight) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010480 RawLightInfo info1 = {.id = 1,
Josep del Rioa1046a82023-08-24 19:57:27 +000010481 .name = "sony1",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010482 .maxBrightness = 255,
10483 .flags = InputLightClass::BRIGHTNESS,
10484 .path = ""};
10485 RawLightInfo info2 = {.id = 2,
Josep del Rioa1046a82023-08-24 19:57:27 +000010486 .name = "sony2",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010487 .maxBrightness = 255,
10488 .flags = InputLightClass::BRIGHTNESS,
10489 .path = ""};
10490 RawLightInfo info3 = {.id = 3,
Josep del Rioa1046a82023-08-24 19:57:27 +000010491 .name = "sony3",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010492 .maxBrightness = 255,
10493 .flags = InputLightClass::BRIGHTNESS,
10494 .path = ""};
10495 RawLightInfo info4 = {.id = 4,
Josep del Rioa1046a82023-08-24 19:57:27 +000010496 .name = "sony4",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010497 .maxBrightness = 255,
10498 .flags = InputLightClass::BRIGHTNESS,
10499 .path = ""};
10500 mFakeEventHub->addRawLightInfo(info1.id, std::move(info1));
10501 mFakeEventHub->addRawLightInfo(info2.id, std::move(info2));
10502 mFakeEventHub->addRawLightInfo(info3.id, std::move(info3));
10503 mFakeEventHub->addRawLightInfo(info4.id, std::move(info4));
10504
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010505 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010506 InputDeviceInfo info;
10507 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010508 std::vector<InputDeviceLightInfo> lights = info.getLights();
10509 ASSERT_EQ(1U, lights.size());
Josep del Rioa1046a82023-08-24 19:57:27 +000010510 ASSERT_STREQ("sony", lights[0].name.c_str());
10511 ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
10512 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10513 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10514
10515 ASSERT_FALSE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10516 ASSERT_TRUE(controller.setLightPlayerId(lights[0].id, LIGHT_PLAYER_ID));
10517 ASSERT_EQ(controller.getLightPlayerId(lights[0].id).value_or(-1), LIGHT_PLAYER_ID);
10518 ASSERT_STREQ("sony", lights[0].name.c_str());
10519}
10520
10521TEST_F(LightControllerTest, PlayerIdLight) {
10522 RawLightInfo info1 = {.id = 1,
10523 .name = "player-1",
10524 .maxBrightness = 255,
10525 .flags = InputLightClass::BRIGHTNESS,
10526 .path = ""};
10527 RawLightInfo info2 = {.id = 2,
10528 .name = "player-2",
10529 .maxBrightness = 255,
10530 .flags = InputLightClass::BRIGHTNESS,
10531 .path = ""};
10532 RawLightInfo info3 = {.id = 3,
10533 .name = "player-3",
10534 .maxBrightness = 255,
10535 .flags = InputLightClass::BRIGHTNESS,
10536 .path = ""};
10537 RawLightInfo info4 = {.id = 4,
10538 .name = "player-4",
10539 .maxBrightness = 255,
10540 .flags = InputLightClass::BRIGHTNESS,
10541 .path = ""};
10542 mFakeEventHub->addRawLightInfo(info1.id, std::move(info1));
10543 mFakeEventHub->addRawLightInfo(info2.id, std::move(info2));
10544 mFakeEventHub->addRawLightInfo(info3.id, std::move(info3));
10545 mFakeEventHub->addRawLightInfo(info4.id, std::move(info4));
10546
10547 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10548 InputDeviceInfo info;
10549 controller.populateDeviceInfo(&info);
10550 std::vector<InputDeviceLightInfo> lights = info.getLights();
10551 ASSERT_EQ(1U, lights.size());
10552 ASSERT_STREQ("player", lights[0].name.c_str());
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010553 ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010554 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10555 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010556
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010557 ASSERT_FALSE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10558 ASSERT_TRUE(controller.setLightPlayerId(lights[0].id, LIGHT_PLAYER_ID));
10559 ASSERT_EQ(controller.getLightPlayerId(lights[0].id).value_or(-1), LIGHT_PLAYER_ID);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010560}
10561
Michael Wrightd02c5b62014-02-10 15:10:22 -080010562} // namespace android