blob: 6c8b65c018ca54807796b43a0e906cbbc55185e7 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Dominik Laskowski2f01d772022-03-23 16:01:29 -070017#include <cinttypes>
18#include <memory>
Harry Cuttsf13161a2023-03-08 14:15:49 +000019#include <optional>
Dominik Laskowski2f01d772022-03-23 16:01:29 -070020
Prabir Pradhan2770d242019-09-02 18:07:11 -070021#include <CursorInputMapper.h>
22#include <InputDevice.h>
23#include <InputMapper.h>
24#include <InputReader.h>
Prabir Pradhan1aed8582019-12-30 11:46:51 -080025#include <InputReaderBase.h>
26#include <InputReaderFactory.h>
Prabir Pradhan2770d242019-09-02 18:07:11 -070027#include <KeyboardInputMapper.h>
28#include <MultiTouchInputMapper.h>
Prabir Pradhan018faea2024-05-08 21:52:54 +000029#include <NotifyArgsBuilders.h>
Chris Ye1dd2e5c2021-04-04 23:12:41 -070030#include <PeripheralController.h>
Chris Yef59a2f42020-10-16 12:55:26 -070031#include <SensorInputMapper.h>
Prabir Pradhan2770d242019-09-02 18:07:11 -070032#include <SingleTouchInputMapper.h>
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000033#include <TestEventMatchers.h>
Prabir Pradhan2770d242019-09-02 18:07:11 -070034#include <TestInputListener.h>
35#include <TouchInputMapper.h>
Prabir Pradhan1aed8582019-12-30 11:46:51 -080036#include <UinputDevice.h>
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070037#include <android-base/thread_annotations.h>
Byoungho Jungda10dd32023-10-06 17:03:45 +090038#include <com_android_input_flags.h>
Michael Wrighta9cf4192022-12-01 23:46:39 +000039#include <ftl/enum.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080040#include <gtest/gtest.h>
Michael Wrighta9cf4192022-12-01 23:46:39 +000041#include <ui/Rotation.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080042
Siarhei Vishniakou21e96e62022-10-27 10:23:37 -070043#include <thread>
Harry Cuttsa5b71292022-11-28 12:56:17 +000044#include "FakeEventHub.h"
Harry Cutts6b5fbc52022-11-28 16:37:43 +000045#include "FakeInputReaderPolicy.h"
Harry Cuttse6512e12022-11-28 18:44:01 +000046#include "InputMapperTest.h"
Harry Cutts144ff542022-11-28 17:41:06 +000047#include "InstrumentedInputReader.h"
Harry Cuttsa5b71292022-11-28 12:56:17 +000048#include "TestConstants.h"
Michael Wrightdde67b82020-10-27 16:09:22 +000049#include "input/DisplayViewport.h"
50#include "input/Input.h"
Michael Wright17db18e2020-06-26 20:51:44 +010051
Michael Wrightd02c5b62014-02-10 15:10:22 -080052namespace android {
53
Dominik Laskowski2f01d772022-03-23 16:01:29 -070054using namespace ftl::flag_operators;
Prabir Pradhan739dca42022-09-09 20:12:01 +000055using testing::AllOf;
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +000056using testing::VariantWith;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070057using std::chrono_literals::operator""ms;
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -080058using std::chrono_literals::operator""s;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -070059
Michael Wrightd02c5b62014-02-10 15:10:22 -080060// Arbitrary display properties.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070061static constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhanc13ff082022-09-08 22:03:30 +000062static const std::string DISPLAY_UNIQUE_ID = "local:1";
Linnan Li13bf76a2024-05-05 19:18:02 +080063static constexpr ui::LogicalDisplayId SECONDARY_DISPLAY_ID =
64 ui::LogicalDisplayId{DISPLAY_ID.val() + 1};
arthurhungcc7f9802020-04-30 17:55:40 +080065static constexpr int32_t DISPLAY_WIDTH = 480;
66static constexpr int32_t DISPLAY_HEIGHT = 800;
Linnan Li13bf76a2024-05-05 19:18:02 +080067static constexpr ui::LogicalDisplayId VIRTUAL_DISPLAY_ID = ui::LogicalDisplayId{1};
arthurhungcc7f9802020-04-30 17:55:40 +080068static constexpr int32_t VIRTUAL_DISPLAY_WIDTH = 400;
69static constexpr int32_t VIRTUAL_DISPLAY_HEIGHT = 500;
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -070070static const char* VIRTUAL_DISPLAY_UNIQUE_ID = "virtual:1";
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -070071static constexpr std::optional<uint8_t> NO_PORT = std::nullopt; // no physical port is specified
Michael Wrightd02c5b62014-02-10 15:10:22 -080072
arthurhungcc7f9802020-04-30 17:55:40 +080073static constexpr int32_t FIRST_SLOT = 0;
74static constexpr int32_t SECOND_SLOT = 1;
75static constexpr int32_t THIRD_SLOT = 2;
76static constexpr int32_t INVALID_TRACKING_ID = -1;
77static constexpr int32_t FIRST_TRACKING_ID = 0;
78static constexpr int32_t SECOND_TRACKING_ID = 1;
79static constexpr int32_t THIRD_TRACKING_ID = 2;
Chris Ye3fdbfef2021-01-06 18:45:18 -080080static constexpr int32_t LIGHT_BRIGHTNESS = 0x55000000;
81static constexpr int32_t LIGHT_COLOR = 0x7F448866;
82static constexpr int32_t LIGHT_PLAYER_ID = 2;
arthurhungcc7f9802020-04-30 17:55:40 +080083
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -080084static constexpr int32_t ACTION_POINTER_0_DOWN =
85 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
86static constexpr int32_t ACTION_POINTER_0_UP =
87 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
88static constexpr int32_t ACTION_POINTER_1_DOWN =
89 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
90static constexpr int32_t ACTION_POINTER_1_UP =
91 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
92
Prabir Pradhanb08a0e82023-09-14 22:28:32 +000093static constexpr uint32_t STYLUS_FUSION_SOURCE =
94 AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_BLUETOOTH_STYLUS;
95
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +000096// Minimum timestamp separation between subsequent input events from a Bluetooth device.
97static constexpr nsecs_t MIN_BLUETOOTH_TIMESTAMP_DELTA = ms2ns(4);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +000098
Byoungho Jungda10dd32023-10-06 17:03:45 +090099namespace input_flags = com::android::input::flags;
100
Michael Wrightd02c5b62014-02-10 15:10:22 -0800101template<typename T>
102static inline T min(T a, T b) {
103 return a < b ? a : b;
104}
105
106static inline float avg(float x, float y) {
107 return (x + y) / 2;
108}
109
Chris Ye3fdbfef2021-01-06 18:45:18 -0800110// Mapping for light color name and the light color
111const std::unordered_map<std::string, LightColor> LIGHT_COLORS = {{"red", LightColor::RED},
112 {"green", LightColor::GREEN},
113 {"blue", LightColor::BLUE}};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800114
Michael Wrighta9cf4192022-12-01 23:46:39 +0000115static ui::Rotation getInverseRotation(ui::Rotation orientation) {
Prabir Pradhanc14266f2021-05-12 15:56:24 -0700116 switch (orientation) {
Michael Wrighta9cf4192022-12-01 23:46:39 +0000117 case ui::ROTATION_90:
118 return ui::ROTATION_270;
119 case ui::ROTATION_270:
120 return ui::ROTATION_90;
Prabir Pradhanc14266f2021-05-12 15:56:24 -0700121 default:
122 return orientation;
123 }
124}
125
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800126static void assertAxisResolution(MultiTouchInputMapper& mapper, int axis, float resolution) {
127 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +0000128 mapper.populateDeviceInfo(info);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800129
130 const InputDeviceInfo::MotionRange* motionRange =
131 info.getMotionRange(axis, AINPUT_SOURCE_TOUCHSCREEN);
132 ASSERT_NEAR(motionRange->resolution, resolution, EPSILON);
133}
134
135static void assertAxisNotPresent(MultiTouchInputMapper& mapper, int axis) {
136 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +0000137 mapper.populateDeviceInfo(info);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -0800138
139 const InputDeviceInfo::MotionRange* motionRange =
140 info.getMotionRange(axis, AINPUT_SOURCE_TOUCHSCREEN);
141 ASSERT_EQ(nullptr, motionRange);
142}
143
Siarhei Vishniakou21e96e62022-10-27 10:23:37 -0700144[[maybe_unused]] static void dumpReader(InputReader& reader) {
145 std::string dump;
146 reader.dump(dump);
147 std::istringstream iss(dump);
148 for (std::string line; std::getline(iss, line);) {
149 ALOGE("%s", line.c_str());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -0800150 std::this_thread::sleep_for(1ms);
Siarhei Vishniakou21e96e62022-10-27 10:23:37 -0700151 }
152}
153
Michael Wrightd02c5b62014-02-10 15:10:22 -0800154// --- FakeInputMapper ---
155
156class FakeInputMapper : public InputMapper {
157 uint32_t mSources;
158 int32_t mKeyboardType;
159 int32_t mMetaState;
160 KeyedVector<int32_t, int32_t> mKeyCodeStates;
161 KeyedVector<int32_t, int32_t> mScanCodeStates;
162 KeyedVector<int32_t, int32_t> mSwitchStates;
Philip Junker4af3b3d2021-12-14 10:36:55 +0100163 // fake mapping which would normally come from keyCharacterMap
164 std::unordered_map<int32_t, int32_t> mKeyCodeMapping;
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800165 std::vector<int32_t> mSupportedKeyCodes;
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700166 std::list<NotifyArgs> mProcessResult;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800167
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700168 std::mutex mLock;
169 std::condition_variable mStateChangedCondition;
170 bool mConfigureWasCalled GUARDED_BY(mLock);
171 bool mResetWasCalled GUARDED_BY(mLock);
172 bool mProcessWasCalled GUARDED_BY(mLock);
173 RawEvent mLastEvent GUARDED_BY(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800174
Arthur Hungc23540e2018-11-29 20:42:11 +0800175 std::optional<DisplayViewport> mViewport;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800176public:
Arpit Singh8e6fb252023-04-06 11:49:17 +0000177 FakeInputMapper(InputDeviceContext& deviceContext, const InputReaderConfiguration& readerConfig,
178 uint32_t sources)
179 : InputMapper(deviceContext, readerConfig),
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800180 mSources(sources),
181 mKeyboardType(AINPUT_KEYBOARD_TYPE_NONE),
Michael Wrightd02c5b62014-02-10 15:10:22 -0800182 mMetaState(0),
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800183 mConfigureWasCalled(false),
184 mResetWasCalled(false),
185 mProcessWasCalled(false) {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800186
Chris Yea52ade12020-08-27 16:49:20 -0700187 virtual ~FakeInputMapper() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800188
189 void setKeyboardType(int32_t keyboardType) {
190 mKeyboardType = keyboardType;
191 }
192
193 void setMetaState(int32_t metaState) {
194 mMetaState = metaState;
195 }
196
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700197 // Sets the return value for the `process` call.
198 void setProcessResult(std::list<NotifyArgs> notifyArgs) {
199 mProcessResult.clear();
200 for (auto notifyArg : notifyArgs) {
201 mProcessResult.push_back(notifyArg);
202 }
203 }
204
Michael Wrightd02c5b62014-02-10 15:10:22 -0800205 void assertConfigureWasCalled() {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700206 std::unique_lock<std::mutex> lock(mLock);
207 base::ScopedLockAssertion assumeLocked(mLock);
208 const bool configureCalled =
209 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
210 return mConfigureWasCalled;
211 });
212 if (!configureCalled) {
213 FAIL() << "Expected configure() to have been called.";
214 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800215 mConfigureWasCalled = false;
216 }
217
218 void assertResetWasCalled() {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700219 std::unique_lock<std::mutex> lock(mLock);
220 base::ScopedLockAssertion assumeLocked(mLock);
221 const bool resetCalled =
222 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
223 return mResetWasCalled;
224 });
225 if (!resetCalled) {
226 FAIL() << "Expected reset() to have been called.";
227 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800228 mResetWasCalled = false;
229 }
230
Prabir Pradhanf8d9e442023-12-06 22:06:13 +0000231 void assertResetWasNotCalled() {
232 std::scoped_lock lock(mLock);
233 ASSERT_FALSE(mResetWasCalled) << "Expected reset to not have been called.";
234 }
235
Yi Kong9b14ac62018-07-17 13:48:38 -0700236 void assertProcessWasCalled(RawEvent* outLastEvent = nullptr) {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700237 std::unique_lock<std::mutex> lock(mLock);
238 base::ScopedLockAssertion assumeLocked(mLock);
239 const bool processCalled =
240 mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
241 return mProcessWasCalled;
242 });
243 if (!processCalled) {
244 FAIL() << "Expected process() to have been called.";
245 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800246 if (outLastEvent) {
247 *outLastEvent = mLastEvent;
248 }
249 mProcessWasCalled = false;
250 }
251
Prabir Pradhanf8d9e442023-12-06 22:06:13 +0000252 void assertProcessWasNotCalled() {
253 std::scoped_lock lock(mLock);
254 ASSERT_FALSE(mProcessWasCalled) << "Expected process to not have been called.";
255 }
256
Michael Wrightd02c5b62014-02-10 15:10:22 -0800257 void setKeyCodeState(int32_t keyCode, int32_t state) {
258 mKeyCodeStates.replaceValueFor(keyCode, state);
259 }
260
261 void setScanCodeState(int32_t scanCode, int32_t state) {
262 mScanCodeStates.replaceValueFor(scanCode, state);
263 }
264
265 void setSwitchState(int32_t switchCode, int32_t state) {
266 mSwitchStates.replaceValueFor(switchCode, state);
267 }
268
269 void addSupportedKeyCode(int32_t keyCode) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800270 mSupportedKeyCodes.push_back(keyCode);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800271 }
272
Philip Junker4af3b3d2021-12-14 10:36:55 +0100273 void addKeyCodeMapping(int32_t fromKeyCode, int32_t toKeyCode) {
274 mKeyCodeMapping.insert_or_assign(fromKeyCode, toKeyCode);
275 }
276
Michael Wrightd02c5b62014-02-10 15:10:22 -0800277private:
Philip Junker4af3b3d2021-12-14 10:36:55 +0100278 uint32_t getSources() const override { return mSources; }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800279
Harry Cuttsd02ea102023-03-17 18:21:30 +0000280 void populateDeviceInfo(InputDeviceInfo& deviceInfo) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800281 InputMapper::populateDeviceInfo(deviceInfo);
282
283 if (mKeyboardType != AINPUT_KEYBOARD_TYPE_NONE) {
Harry Cuttsd02ea102023-03-17 18:21:30 +0000284 deviceInfo.setKeyboardType(mKeyboardType);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800285 }
286 }
287
Arpit Singhed6c3de2023-04-05 19:24:37 +0000288 std::list<NotifyArgs> reconfigure(nsecs_t, const InputReaderConfiguration& config,
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000289 ConfigurationChanges changes) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700290 std::scoped_lock<std::mutex> lock(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800291 mConfigureWasCalled = true;
Arthur Hungc23540e2018-11-29 20:42:11 +0800292
293 // Find the associated viewport if exist.
Nathaniel R. Lewis26ec2222020-01-10 16:30:54 -0800294 const std::optional<uint8_t> displayPort = getDeviceContext().getAssociatedDisplayPort();
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000295 if (displayPort && changes.test(InputReaderConfiguration::Change::DISPLAY_INFO)) {
Arpit Singhed6c3de2023-04-05 19:24:37 +0000296 mViewport = config.getDisplayViewportByPort(*displayPort);
Arthur Hungc23540e2018-11-29 20:42:11 +0800297 }
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700298
299 mStateChangedCondition.notify_all();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700300 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800301 }
302
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700303 std::list<NotifyArgs> reset(nsecs_t) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700304 std::scoped_lock<std::mutex> lock(mLock);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800305 mResetWasCalled = true;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700306 mStateChangedCondition.notify_all();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700307 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800308 }
309
Harry Cuttsa32a1192024-06-04 15:10:31 +0000310 std::list<NotifyArgs> process(const RawEvent& rawEvent) override {
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700311 std::scoped_lock<std::mutex> lock(mLock);
Harry Cuttsa32a1192024-06-04 15:10:31 +0000312 mLastEvent = rawEvent;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800313 mProcessWasCalled = true;
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700314 mStateChangedCondition.notify_all();
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -0700315 return mProcessResult;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800316 }
317
Chris Yea52ade12020-08-27 16:49:20 -0700318 int32_t getKeyCodeState(uint32_t, int32_t keyCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800319 ssize_t index = mKeyCodeStates.indexOfKey(keyCode);
320 return index >= 0 ? mKeyCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
321 }
322
Philip Junker4af3b3d2021-12-14 10:36:55 +0100323 int32_t getKeyCodeForKeyLocation(int32_t locationKeyCode) const override {
324 auto it = mKeyCodeMapping.find(locationKeyCode);
325 return it != mKeyCodeMapping.end() ? it->second : locationKeyCode;
326 }
327
Chris Yea52ade12020-08-27 16:49:20 -0700328 int32_t getScanCodeState(uint32_t, int32_t scanCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800329 ssize_t index = mScanCodeStates.indexOfKey(scanCode);
330 return index >= 0 ? mScanCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
331 }
332
Chris Yea52ade12020-08-27 16:49:20 -0700333 int32_t getSwitchState(uint32_t, int32_t switchCode) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800334 ssize_t index = mSwitchStates.indexOfKey(switchCode);
335 return index >= 0 ? mSwitchStates.valueAt(index) : AKEY_STATE_UNKNOWN;
336 }
337
Chris Yea52ade12020-08-27 16:49:20 -0700338 // Return true if the device has non-empty key layout.
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700339 bool markSupportedKeyCodes(uint32_t, const std::vector<int32_t>& keyCodes,
Chris Yea52ade12020-08-27 16:49:20 -0700340 uint8_t* outFlags) override {
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700341 for (size_t i = 0; i < keyCodes.size(); i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800342 for (size_t j = 0; j < mSupportedKeyCodes.size(); j++) {
343 if (keyCodes[i] == mSupportedKeyCodes[j]) {
344 outFlags[i] = 1;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800345 }
346 }
347 }
Chris Yea52ade12020-08-27 16:49:20 -0700348 bool result = mSupportedKeyCodes.size() > 0;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800349 return result;
350 }
351
352 virtual int32_t getMetaState() {
353 return mMetaState;
354 }
355
356 virtual void fadePointer() {
357 }
Arthur Hungc23540e2018-11-29 20:42:11 +0800358
Linnan Li13bf76a2024-05-05 19:18:02 +0800359 virtual std::optional<ui::LogicalDisplayId> getAssociatedDisplay() {
Arthur Hungc23540e2018-11-29 20:42:11 +0800360 if (mViewport) {
361 return std::make_optional(mViewport->displayId);
362 }
363 return std::nullopt;
364 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800365};
366
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700367// --- InputReaderPolicyTest ---
368class InputReaderPolicyTest : public testing::Test {
Siarhei Vishniakoucd7ac1e2018-10-15 13:39:50 -0700369protected:
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700370 sp<FakeInputReaderPolicy> mFakePolicy;
371
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700372 void SetUp() override { mFakePolicy = sp<FakeInputReaderPolicy>::make(); }
Chris Yea52ade12020-08-27 16:49:20 -0700373 void TearDown() override { mFakePolicy.clear(); }
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700374};
375
376/**
377 * Check that empty set of viewports is an acceptable configuration.
378 * Also try to get internal viewport two different ways - by type and by uniqueId.
379 *
380 * There will be confusion if two viewports with empty uniqueId and identical type are present.
381 * Such configuration is not currently allowed.
382 */
383TEST_F(InputReaderPolicyTest, Viewports_GetCleared) {
Siarhei Vishniakoucd7ac1e2018-10-15 13:39:50 -0700384 static const std::string uniqueId = "local:0";
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700385
386 // We didn't add any viewports yet, so there shouldn't be any.
387 std::optional<DisplayViewport> internalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100388 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700389 ASSERT_FALSE(internalViewport);
390
391 // Add an internal viewport, then clear it
Michael Wrighta9cf4192022-12-01 23:46:39 +0000392 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000393 /*isActive=*/true, uniqueId, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700394
395 // Check matching by uniqueId
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700396 internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700397 ASSERT_TRUE(internalViewport);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100398 ASSERT_EQ(ViewportType::INTERNAL, internalViewport->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700399
400 // Check matching by viewport type
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100401 internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700402 ASSERT_TRUE(internalViewport);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700403 ASSERT_EQ(uniqueId, internalViewport->uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700404
405 mFakePolicy->clearViewports();
406 // Make sure nothing is found after clear
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700407 internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700408 ASSERT_FALSE(internalViewport);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100409 internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700410 ASSERT_FALSE(internalViewport);
411}
412
413TEST_F(InputReaderPolicyTest, Viewports_GetByType) {
414 const std::string internalUniqueId = "local:0";
415 const std::string externalUniqueId = "local:1";
416 const std::string virtualUniqueId1 = "virtual:2";
417 const std::string virtualUniqueId2 = "virtual:3";
Linnan Li13bf76a2024-05-05 19:18:02 +0800418 constexpr ui::LogicalDisplayId virtualDisplayId1 = ui::LogicalDisplayId{2};
419 constexpr ui::LogicalDisplayId virtualDisplayId2 = ui::LogicalDisplayId{3};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700420
421 // Add an internal viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000422 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000423 /*isActive=*/true, internalUniqueId, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000424 ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700425 // Add an external viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000426 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000427 /*isActive=*/true, externalUniqueId, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000428 ViewportType::EXTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700429 // Add an virtual viewport
430 mFakePolicy->addDisplayViewport(virtualDisplayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000431 ui::ROTATION_0, /*isActive=*/true, virtualUniqueId1, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000432 ViewportType::VIRTUAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700433 // Add another virtual viewport
434 mFakePolicy->addDisplayViewport(virtualDisplayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000435 ui::ROTATION_0, /*isActive=*/true, virtualUniqueId2, NO_PORT,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000436 ViewportType::VIRTUAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700437
438 // Check matching by type for internal
439 std::optional<DisplayViewport> internalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100440 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700441 ASSERT_TRUE(internalViewport);
442 ASSERT_EQ(internalUniqueId, internalViewport->uniqueId);
443
444 // Check matching by type for external
445 std::optional<DisplayViewport> externalViewport =
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100446 mFakePolicy->getDisplayViewportByType(ViewportType::EXTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700447 ASSERT_TRUE(externalViewport);
448 ASSERT_EQ(externalUniqueId, externalViewport->uniqueId);
449
450 // Check matching by uniqueId for virtual viewport #1
451 std::optional<DisplayViewport> virtualViewport1 =
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700452 mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId1);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700453 ASSERT_TRUE(virtualViewport1);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100454 ASSERT_EQ(ViewportType::VIRTUAL, virtualViewport1->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700455 ASSERT_EQ(virtualUniqueId1, virtualViewport1->uniqueId);
456 ASSERT_EQ(virtualDisplayId1, virtualViewport1->displayId);
457
458 // Check matching by uniqueId for virtual viewport #2
459 std::optional<DisplayViewport> virtualViewport2 =
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700460 mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId2);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700461 ASSERT_TRUE(virtualViewport2);
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100462 ASSERT_EQ(ViewportType::VIRTUAL, virtualViewport2->type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700463 ASSERT_EQ(virtualUniqueId2, virtualViewport2->uniqueId);
464 ASSERT_EQ(virtualDisplayId2, virtualViewport2->displayId);
465}
466
467
468/**
469 * We can have 2 viewports of the same kind. We can distinguish them by uniqueId, and confirm
470 * that lookup works by checking display id.
471 * Check that 2 viewports of each kind is possible, for all existing viewport types.
472 */
473TEST_F(InputReaderPolicyTest, Viewports_TwoOfSameType) {
474 const std::string uniqueId1 = "uniqueId1";
475 const std::string uniqueId2 = "uniqueId2";
Linnan Li13bf76a2024-05-05 19:18:02 +0800476 constexpr ui::LogicalDisplayId displayId1 = ui::LogicalDisplayId{2};
477 constexpr ui::LogicalDisplayId displayId2 = ui::LogicalDisplayId{3};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700478
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100479 std::vector<ViewportType> types = {ViewportType::INTERNAL, ViewportType::EXTERNAL,
480 ViewportType::VIRTUAL};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700481 for (const ViewportType& type : types) {
482 mFakePolicy->clearViewports();
483 // Add a viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000484 mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000485 /*isActive=*/true, uniqueId1, NO_PORT, type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700486 // Add another viewport
Michael Wrighta9cf4192022-12-01 23:46:39 +0000487 mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000488 /*isActive=*/true, uniqueId2, NO_PORT, type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700489
490 // Check that correct display viewport was returned by comparing the display IDs.
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700491 std::optional<DisplayViewport> viewport1 =
492 mFakePolicy->getDisplayViewportByUniqueId(uniqueId1);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700493 ASSERT_TRUE(viewport1);
494 ASSERT_EQ(displayId1, viewport1->displayId);
495 ASSERT_EQ(type, viewport1->type);
496
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700497 std::optional<DisplayViewport> viewport2 =
498 mFakePolicy->getDisplayViewportByUniqueId(uniqueId2);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700499 ASSERT_TRUE(viewport2);
500 ASSERT_EQ(displayId2, viewport2->displayId);
501 ASSERT_EQ(type, viewport2->type);
502
503 // When there are multiple viewports of the same kind, and uniqueId is not specified
504 // in the call to getDisplayViewport, then that situation is not supported.
505 // The viewports can be stored in any order, so we cannot rely on the order, since that
506 // is just implementation detail.
507 // However, we can check that it still returns *a* viewport, we just cannot assert
508 // which one specifically is returned.
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700509 std::optional<DisplayViewport> someViewport = mFakePolicy->getDisplayViewportByType(type);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -0700510 ASSERT_TRUE(someViewport);
511 }
512}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800513
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700514/**
Michael Wrightdde67b82020-10-27 16:09:22 +0000515 * When we have multiple internal displays make sure we always return the default display when
516 * querying by type.
517 */
518TEST_F(InputReaderPolicyTest, Viewports_ByTypeReturnsDefaultForInternal) {
519 const std::string uniqueId1 = "uniqueId1";
520 const std::string uniqueId2 = "uniqueId2";
Linnan Li13bf76a2024-05-05 19:18:02 +0800521 constexpr ui::LogicalDisplayId nonDefaultDisplayId = ui::LogicalDisplayId{2};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700522 ASSERT_NE(nonDefaultDisplayId, ui::LogicalDisplayId::DEFAULT)
523 << "Test display ID should not be ui::LogicalDisplayId::DEFAULT ";
Michael Wrightdde67b82020-10-27 16:09:22 +0000524
525 // Add the default display first and ensure it gets returned.
526 mFakePolicy->clearViewports();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700527 mFakePolicy->addDisplayViewport(ui::LogicalDisplayId::DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000528 ui::ROTATION_0, /*isActive=*/true, uniqueId1, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000529 ViewportType::INTERNAL);
530 mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000531 ui::ROTATION_0, /*isActive=*/true, uniqueId2, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000532 ViewportType::INTERNAL);
533
534 std::optional<DisplayViewport> viewport =
535 mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
536 ASSERT_TRUE(viewport);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700537 ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, viewport->displayId);
Michael Wrightdde67b82020-10-27 16:09:22 +0000538 ASSERT_EQ(ViewportType::INTERNAL, viewport->type);
539
540 // Add the default display second to make sure order doesn't matter.
541 mFakePolicy->clearViewports();
542 mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000543 ui::ROTATION_0, /*isActive=*/true, uniqueId2, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000544 ViewportType::INTERNAL);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700545 mFakePolicy->addDisplayViewport(ui::LogicalDisplayId::DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +0000546 ui::ROTATION_0, /*isActive=*/true, uniqueId1, NO_PORT,
Michael Wrightdde67b82020-10-27 16:09:22 +0000547 ViewportType::INTERNAL);
548
549 viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
550 ASSERT_TRUE(viewport);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700551 ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, viewport->displayId);
Michael Wrightdde67b82020-10-27 16:09:22 +0000552 ASSERT_EQ(ViewportType::INTERNAL, viewport->type);
553}
554
555/**
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700556 * Check getDisplayViewportByPort
557 */
558TEST_F(InputReaderPolicyTest, Viewports_GetByPort) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +0100559 constexpr ViewportType type = ViewportType::EXTERNAL;
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700560 const std::string uniqueId1 = "uniqueId1";
561 const std::string uniqueId2 = "uniqueId2";
Linnan Li13bf76a2024-05-05 19:18:02 +0800562 constexpr ui::LogicalDisplayId displayId1 = ui::LogicalDisplayId{1};
563 constexpr ui::LogicalDisplayId displayId2 = ui::LogicalDisplayId{2};
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700564 const uint8_t hdmi1 = 0;
565 const uint8_t hdmi2 = 1;
566 const uint8_t hdmi3 = 2;
567
568 mFakePolicy->clearViewports();
569 // Add a viewport that's associated with some display port that's not of interest.
Michael Wrighta9cf4192022-12-01 23:46:39 +0000570 mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000571 /*isActive=*/true, uniqueId1, hdmi3, type);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700572 // Add another viewport, connected to HDMI1 port
Michael Wrighta9cf4192022-12-01 23:46:39 +0000573 mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +0000574 /*isActive=*/true, uniqueId2, hdmi1, type);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -0700575
576 // Check that correct display viewport was returned by comparing the display ports.
577 std::optional<DisplayViewport> hdmi1Viewport = mFakePolicy->getDisplayViewportByPort(hdmi1);
578 ASSERT_TRUE(hdmi1Viewport);
579 ASSERT_EQ(displayId2, hdmi1Viewport->displayId);
580 ASSERT_EQ(uniqueId2, hdmi1Viewport->uniqueId);
581
582 // Check that we can still get the same viewport using the uniqueId
583 hdmi1Viewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId2);
584 ASSERT_TRUE(hdmi1Viewport);
585 ASSERT_EQ(displayId2, hdmi1Viewport->displayId);
586 ASSERT_EQ(uniqueId2, hdmi1Viewport->uniqueId);
587 ASSERT_EQ(type, hdmi1Viewport->type);
588
589 // Check that we cannot find a port with "HDMI2", because we never added one
590 std::optional<DisplayViewport> hdmi2Viewport = mFakePolicy->getDisplayViewportByPort(hdmi2);
591 ASSERT_FALSE(hdmi2Viewport);
592}
593
Michael Wrightd02c5b62014-02-10 15:10:22 -0800594// --- InputReaderTest ---
595
596class InputReaderTest : public testing::Test {
597protected:
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700598 std::unique_ptr<TestInputListener> mFakeListener;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800599 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou3bc7e092019-07-24 17:43:30 -0700600 std::shared_ptr<FakeEventHub> mFakeEventHub;
Prabir Pradhan28efc192019-11-05 01:10:04 +0000601 std::unique_ptr<InstrumentedInputReader> mReader;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800602
Chris Yea52ade12020-08-27 16:49:20 -0700603 void SetUp() override {
Siarhei Vishniakou3bc7e092019-07-24 17:43:30 -0700604 mFakeEventHub = std::make_unique<FakeEventHub>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700605 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700606 mFakeListener = std::make_unique<TestInputListener>();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800607
Prabir Pradhan28efc192019-11-05 01:10:04 +0000608 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700609 *mFakeListener);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800610 }
611
Chris Yea52ade12020-08-27 16:49:20 -0700612 void TearDown() override {
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700613 mFakeListener.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800614 mFakePolicy.clear();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800615 }
616
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700617 void addDevice(int32_t eventHubId, const std::string& name,
618 ftl::Flags<InputDeviceClass> classes, const PropertyMap* configuration) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800619 mFakeEventHub->addDevice(eventHubId, name, classes);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800620
621 if (configuration) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800622 mFakeEventHub->addConfigurationMap(eventHubId, configuration);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800623 }
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000624 mReader->loopOnce();
625 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700626 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Prabir Pradhane3da4bb2023-04-05 23:51:23 +0000627 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyInputDevicesChangedWasCalled());
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700628 ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800629 }
630
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800631 void disableDevice(int32_t deviceId) {
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700632 mFakePolicy->addDisabledDevice(deviceId);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000633 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::ENABLED_STATE);
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700634 }
635
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800636 void enableDevice(int32_t deviceId) {
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700637 mFakePolicy->removeDisabledDevice(deviceId);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +0000638 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::ENABLED_STATE);
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700639 }
640
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800641 FakeInputMapper& addDeviceWithFakeInputMapper(int32_t deviceId, int32_t eventHubId,
Chris Ye1b0c7342020-07-28 21:57:03 -0700642 const std::string& name,
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700643 ftl::Flags<InputDeviceClass> classes,
644 uint32_t sources,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800645 const PropertyMap* configuration) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800646 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, name);
Arpit Singh8e6fb252023-04-06 11:49:17 +0000647 FakeInputMapper& mapper =
648 device->addMapper<FakeInputMapper>(eventHubId,
649 mFakePolicy->getReaderConfiguration(), sources);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -0800650 mReader->pushNextDevice(device);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800651 addDevice(eventHubId, name, classes, configuration);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800652 return mapper;
653 }
654};
655
Chris Ye98d3f532020-10-01 21:48:59 -0700656TEST_F(InputReaderTest, PolicyGetInputDevices) {
657 ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard", InputDeviceClass::KEYBOARD, nullptr));
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700658 ASSERT_NO_FATAL_FAILURE(addDevice(2, "ignored", ftl::Flags<InputDeviceClass>(0),
Chris Ye98d3f532020-10-01 21:48:59 -0700659 nullptr)); // no classes so device will be ignored
Michael Wrightd02c5b62014-02-10 15:10:22 -0800660
661 // Should also have received a notification describing the new input devices.
Chris Ye98d3f532020-10-01 21:48:59 -0700662 const std::vector<InputDeviceInfo>& inputDevices = mFakePolicy->getInputDevices();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800663 ASSERT_EQ(1U, inputDevices.size());
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800664 ASSERT_EQ(END_RESERVED_ID + 1, inputDevices[0].getId());
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100665 ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800666 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, inputDevices[0].getKeyboardType());
667 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, inputDevices[0].getSources());
Siarhei Vishniakou1983a712021-06-04 19:27:09 +0000668 ASSERT_EQ(0U, inputDevices[0].getMotionRanges().size());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800669}
670
Vaibhav Devmurari5fc7d852023-03-17 18:43:33 +0000671TEST_F(InputReaderTest, InputDeviceRecreatedOnSysfsNodeChanged) {
672 ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard", InputDeviceClass::KEYBOARD, nullptr));
673 mFakeEventHub->setSysfsRootPath(1, "xyz");
674
675 // Should also have received a notification describing the new input device.
676 ASSERT_EQ(1U, mFakePolicy->getInputDevices().size());
677 InputDeviceInfo inputDevice = mFakePolicy->getInputDevices()[0];
678 ASSERT_EQ(0U, inputDevice.getLights().size());
679
680 RawLightInfo infoMonolight = {.id = 123,
681 .name = "mono_keyboard_backlight",
682 .maxBrightness = 255,
683 .flags = InputLightClass::BRIGHTNESS,
684 .path = ""};
685 mFakeEventHub->addRawLightInfo(/*rawId=*/123, std::move(infoMonolight));
686 mReader->sysfsNodeChanged("xyz");
687 mReader->loopOnce();
688
689 // Should also have received a notification describing the new recreated input device.
690 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
691 inputDevice = mFakePolicy->getInputDevices()[0];
692 ASSERT_EQ(1U, inputDevice.getLights().size());
693}
694
Chris Yee7310032020-09-22 15:36:28 -0700695TEST_F(InputReaderTest, GetMergedInputDevices) {
696 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
697 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
698 // Add two subdevices to device
699 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
700 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000701 device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
702 AINPUT_SOURCE_KEYBOARD);
703 device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
704 AINPUT_SOURCE_KEYBOARD);
Chris Yee7310032020-09-22 15:36:28 -0700705
706 // Push same device instance for next device to be added, so they'll have same identifier.
707 mReader->pushNextDevice(device);
708 mReader->pushNextDevice(device);
709 ASSERT_NO_FATAL_FAILURE(
710 addDevice(eventHubIds[0], "fake1", InputDeviceClass::KEYBOARD, nullptr));
711 ASSERT_NO_FATAL_FAILURE(
712 addDevice(eventHubIds[1], "fake2", InputDeviceClass::KEYBOARD, nullptr));
713
714 // Two devices will be merged to one input device as they have same identifier
Siarhei Vishniakou1983a712021-06-04 19:27:09 +0000715 ASSERT_EQ(1U, mFakePolicy->getInputDevices().size());
Chris Yee7310032020-09-22 15:36:28 -0700716}
717
Chris Yee14523a2020-12-19 13:46:00 -0800718TEST_F(InputReaderTest, GetMergedInputDevicesEnabled) {
719 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
720 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
721 // Add two subdevices to device
722 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
723 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000724 device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
725 AINPUT_SOURCE_KEYBOARD);
726 device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
727 AINPUT_SOURCE_KEYBOARD);
Chris Yee14523a2020-12-19 13:46:00 -0800728
729 // Push same device instance for next device to be added, so they'll have same identifier.
730 mReader->pushNextDevice(device);
731 mReader->pushNextDevice(device);
732 // Sensor device is initially disabled
733 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1",
734 InputDeviceClass::KEYBOARD | InputDeviceClass::SENSOR,
735 nullptr));
736 // Device is disabled because the only sub device is a sensor device and disabled initially.
737 ASSERT_FALSE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
738 ASSERT_FALSE(device->isEnabled());
739 ASSERT_NO_FATAL_FAILURE(
740 addDevice(eventHubIds[1], "fake2", InputDeviceClass::KEYBOARD, nullptr));
741 // The merged device is enabled if any sub device is enabled
742 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
743 ASSERT_TRUE(device->isEnabled());
744}
745
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700746TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800747 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700748 constexpr ftl::Flags<InputDeviceClass> deviceClass(InputDeviceClass::KEYBOARD);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800749 constexpr int32_t eventHubId = 1;
750 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700751 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000752 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
753 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -0800754 mReader->pushNextDevice(device);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800755 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700756
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700757 NotifyDeviceResetArgs resetArgs;
758 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700759 ASSERT_EQ(deviceId, resetArgs.deviceId);
760
761 ASSERT_EQ(device->isEnabled(), true);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800762 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000763 mReader->loopOnce();
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700764
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700765 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700766 ASSERT_EQ(deviceId, resetArgs.deviceId);
767 ASSERT_EQ(device->isEnabled(), false);
768
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800769 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000770 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700771 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700772 ASSERT_EQ(device->isEnabled(), false);
773
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800774 enableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000775 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700776 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700777 ASSERT_EQ(deviceId, resetArgs.deviceId);
778 ASSERT_EQ(device->isEnabled(), true);
779}
780
Michael Wrightd02c5b62014-02-10 15:10:22 -0800781TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800782 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700783 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800784 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800785 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800786 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800787 AINPUT_SOURCE_KEYBOARD, nullptr);
788 mapper.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800789
790 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(0,
791 AINPUT_SOURCE_ANY, AKEYCODE_A))
792 << "Should return unknown when the device id is >= 0 but unknown.";
793
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800794 ASSERT_EQ(AKEY_STATE_UNKNOWN,
795 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
796 << "Should return unknown when the device id is valid but the sources are not "
797 "supported by the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800798
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800799 ASSERT_EQ(AKEY_STATE_DOWN,
800 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
801 AKEYCODE_A))
802 << "Should return value provided by mapper when device id is valid and the device "
803 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800804
805 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(-1,
806 AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
807 << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
808
809 ASSERT_EQ(AKEY_STATE_DOWN, mReader->getKeyCodeState(-1,
810 AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
811 << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
812}
813
Philip Junker4af3b3d2021-12-14 10:36:55 +0100814TEST_F(InputReaderTest, GetKeyCodeForKeyLocation_ForwardsRequestsToMappers) {
815 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
816 constexpr int32_t eventHubId = 1;
817 FakeInputMapper& mapper = addDeviceWithFakeInputMapper(deviceId, eventHubId, "keyboard",
818 InputDeviceClass::KEYBOARD,
819 AINPUT_SOURCE_KEYBOARD, nullptr);
820 mapper.addKeyCodeMapping(AKEYCODE_Y, AKEYCODE_Z);
821
822 ASSERT_EQ(AKEYCODE_UNKNOWN, mReader->getKeyCodeForKeyLocation(0, AKEYCODE_Y))
823 << "Should return unknown when the device with the specified id is not found.";
824
825 ASSERT_EQ(AKEYCODE_Z, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_Y))
826 << "Should return correct mapping when device id is valid and mapping exists.";
827
828 ASSERT_EQ(AKEYCODE_A, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_A))
829 << "Should return the location key code when device id is valid and there's no "
830 "mapping.";
831}
832
833TEST_F(InputReaderTest, GetKeyCodeForKeyLocation_NoKeyboardMapper) {
834 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
835 constexpr int32_t eventHubId = 1;
836 FakeInputMapper& mapper = addDeviceWithFakeInputMapper(deviceId, eventHubId, "joystick",
837 InputDeviceClass::JOYSTICK,
838 AINPUT_SOURCE_GAMEPAD, nullptr);
839 mapper.addKeyCodeMapping(AKEYCODE_Y, AKEYCODE_Z);
840
841 ASSERT_EQ(AKEYCODE_UNKNOWN, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_Y))
842 << "Should return unknown when the device id is valid but there is no keyboard mapper";
843}
844
Michael Wrightd02c5b62014-02-10 15:10:22 -0800845TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800846 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700847 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800848 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800849 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800850 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800851 AINPUT_SOURCE_KEYBOARD, nullptr);
852 mapper.setScanCodeState(KEY_A, AKEY_STATE_DOWN);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800853
854 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(0,
855 AINPUT_SOURCE_ANY, KEY_A))
856 << "Should return unknown when the device id is >= 0 but unknown.";
857
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800858 ASSERT_EQ(AKEY_STATE_UNKNOWN,
859 mReader->getScanCodeState(deviceId, AINPUT_SOURCE_TRACKBALL, KEY_A))
860 << "Should return unknown when the device id is valid but the sources are not "
861 "supported by the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800862
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800863 ASSERT_EQ(AKEY_STATE_DOWN,
864 mReader->getScanCodeState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
865 KEY_A))
866 << "Should return value provided by mapper when device id is valid and the device "
867 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800868
869 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(-1,
870 AINPUT_SOURCE_TRACKBALL, KEY_A))
871 << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
872
873 ASSERT_EQ(AKEY_STATE_DOWN, mReader->getScanCodeState(-1,
874 AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, KEY_A))
875 << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
876}
877
878TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800879 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700880 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800881 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800882 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800883 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800884 AINPUT_SOURCE_KEYBOARD, nullptr);
885 mapper.setSwitchState(SW_LID, AKEY_STATE_DOWN);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800886
887 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(0,
888 AINPUT_SOURCE_ANY, SW_LID))
889 << "Should return unknown when the device id is >= 0 but unknown.";
890
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800891 ASSERT_EQ(AKEY_STATE_UNKNOWN,
892 mReader->getSwitchState(deviceId, AINPUT_SOURCE_TRACKBALL, SW_LID))
893 << "Should return unknown when the device id is valid but the sources are not "
894 "supported by the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800895
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800896 ASSERT_EQ(AKEY_STATE_DOWN,
897 mReader->getSwitchState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
898 SW_LID))
899 << "Should return value provided by mapper when device id is valid and the device "
900 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800901
902 ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(-1,
903 AINPUT_SOURCE_TRACKBALL, SW_LID))
904 << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
905
906 ASSERT_EQ(AKEY_STATE_DOWN, mReader->getSwitchState(-1,
907 AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, SW_LID))
908 << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
909}
910
911TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800912 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700913 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800914 constexpr int32_t eventHubId = 1;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800915 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800916 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800917 AINPUT_SOURCE_KEYBOARD, nullptr);
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100918
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800919 mapper.addSupportedKeyCode(AKEYCODE_A);
920 mapper.addSupportedKeyCode(AKEYCODE_B);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800921
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700922 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800923 uint8_t flags[4] = { 0, 0, 0, 1 };
924
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700925 ASSERT_FALSE(mReader->hasKeys(0, AINPUT_SOURCE_ANY, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800926 << "Should return false when device id is >= 0 but unknown.";
927 ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
928
929 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700930 ASSERT_FALSE(mReader->hasKeys(deviceId, AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800931 << "Should return false when device id is valid but the sources are not supported by "
932 "the device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800933 ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
934
935 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700936 ASSERT_TRUE(mReader->hasKeys(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800937 keyCodes, flags))
938 << "Should return value provided by mapper when device id is valid and the device "
939 "supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800940 ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
941
942 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700943 ASSERT_FALSE(mReader->hasKeys(-1, AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
944 << "Should return false when the device id is < 0 but the sources are not supported by "
945 "any device.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800946 ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
947
948 flags[3] = 1;
Siarhei Vishniakou74007942022-06-13 13:57:47 -0700949 ASSERT_TRUE(
950 mReader->hasKeys(-1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
951 << "Should return value provided by mapper when device id is < 0 and one of the "
952 "devices supports some of the sources.";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800953 ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
954}
955
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000956TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800957 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700958 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000959 constexpr nsecs_t when = 0;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800960 constexpr int32_t eventHubId = 1;
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000961 constexpr nsecs_t readTime = 2;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800962 FakeInputMapper& mapper =
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800963 addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800964 AINPUT_SOURCE_KEYBOARD, nullptr);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800965
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000966 mFakeEventHub->enqueueEvent(when, readTime, eventHubId, EV_KEY, KEY_A, 1);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000967 mReader->loopOnce();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800968 ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty());
969
970 RawEvent event;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800971 ASSERT_NO_FATAL_FAILURE(mapper.assertProcessWasCalled(&event));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +0000972 ASSERT_EQ(when, event.when);
973 ASSERT_EQ(readTime, event.readTime);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800974 ASSERT_EQ(eventHubId, event.deviceId);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800975 ASSERT_EQ(EV_KEY, event.type);
976 ASSERT_EQ(KEY_A, event.code);
977 ASSERT_EQ(1, event.value);
978}
979
Garfield Tan1c7bc862020-01-28 13:24:04 -0800980TEST_F(InputReaderTest, DeviceReset_RandomId) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800981 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -0700982 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800983 constexpr int32_t eventHubId = 1;
984 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
Prabir Pradhan42611e02018-11-27 14:04:02 -0800985 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +0000986 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
987 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -0800988 mReader->pushNextDevice(device);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -0800989 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Prabir Pradhan42611e02018-11-27 14:04:02 -0800990
991 NotifyDeviceResetArgs resetArgs;
992 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800993 int32_t prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -0800994
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -0800995 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +0000996 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -0700997 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tan1c7bc862020-01-28 13:24:04 -0800998 ASSERT_NE(prevId, resetArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800999 prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001000
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001001 enableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001002 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -07001003 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tan1c7bc862020-01-28 13:24:04 -08001004 ASSERT_NE(prevId, resetArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001005 prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001006
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001007 disableDevice(deviceId);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001008 mReader->loopOnce();
Prabir Pradhan2574dfa2019-10-16 16:35:07 -07001009 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
Garfield Tan1c7bc862020-01-28 13:24:04 -08001010 ASSERT_NE(prevId, resetArgs.id);
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001011 prevId = resetArgs.id;
Prabir Pradhan42611e02018-11-27 14:04:02 -08001012}
1013
Garfield Tan1c7bc862020-01-28 13:24:04 -08001014TEST_F(InputReaderTest, DeviceReset_GenerateIdWithInputReaderSource) {
1015 constexpr int32_t deviceId = 1;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001016 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Garfield Tan1c7bc862020-01-28 13:24:04 -08001017 constexpr int32_t eventHubId = 1;
1018 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
1019 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +00001020 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
1021 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001022 mReader->pushNextDevice(device);
Garfield Tan1c7bc862020-01-28 13:24:04 -08001023 ASSERT_NO_FATAL_FAILURE(addDevice(deviceId, "fake", deviceClass, nullptr));
1024
1025 NotifyDeviceResetArgs resetArgs;
1026 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1027 ASSERT_EQ(IdGenerator::Source::INPUT_READER, IdGenerator::getSource(resetArgs.id));
1028}
1029
Arthur Hungc23540e2018-11-29 20:42:11 +08001030TEST_F(InputReaderTest, Device_CanDispatchToDisplay) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001031 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001032 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001033 constexpr int32_t eventHubId = 1;
Arthur Hungc23540e2018-11-29 20:42:11 +08001034 const char* DEVICE_LOCATION = "USB1";
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001035 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
1036 FakeInputMapper& mapper =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001037 device->addMapper<FakeInputMapper>(eventHubId, mFakePolicy->getReaderConfiguration(),
1038 AINPUT_SOURCE_TOUCHSCREEN);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001039 mReader->pushNextDevice(device);
Arthur Hungc23540e2018-11-29 20:42:11 +08001040
1041 const uint8_t hdmi1 = 1;
1042
1043 // Associated touch screen with second display.
1044 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
1045
1046 // Add default and second display.
Prabir Pradhan28efc192019-11-05 01:10:04 +00001047 mFakePolicy->clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00001048 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00001049 /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL);
Arthur Hungc23540e2018-11-29 20:42:11 +08001050 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +00001051 ui::ROTATION_0, /*isActive=*/true, "local:1", hdmi1,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01001052 ViewportType::EXTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001053 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::DISPLAY_INFO);
Siarhei Vishniakou6cbc9782019-11-15 17:59:25 +00001054 mReader->loopOnce();
Prabir Pradhan28efc192019-11-05 01:10:04 +00001055
1056 // Add the device, and make sure all of the callbacks are triggered.
1057 // The device is added after the input port associations are processed since
1058 // we do not yet support dynamic device-to-display associations.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08001059 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Prabir Pradhan28efc192019-11-05 01:10:04 +00001060 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001061 ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
Arthur Hungc23540e2018-11-29 20:42:11 +08001062
Arthur Hung2c9a3342019-07-23 14:18:59 +08001063 // Device should only dispatch to the specified display.
Arthur Hungc23540e2018-11-29 20:42:11 +08001064 ASSERT_EQ(deviceId, device->getId());
1065 ASSERT_FALSE(mReader->canDispatchToDisplay(deviceId, DISPLAY_ID));
1066 ASSERT_TRUE(mReader->canDispatchToDisplay(deviceId, SECONDARY_DISPLAY_ID));
Arthur Hung2c9a3342019-07-23 14:18:59 +08001067
1068 // Can't dispatch event from a disabled device.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08001069 disableDevice(deviceId);
Prabir Pradhan28efc192019-11-05 01:10:04 +00001070 mReader->loopOnce();
Arthur Hung2c9a3342019-07-23 14:18:59 +08001071 ASSERT_FALSE(mReader->canDispatchToDisplay(deviceId, SECONDARY_DISPLAY_ID));
Arthur Hungc23540e2018-11-29 20:42:11 +08001072}
1073
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001074TEST_F(InputReaderTest, WhenEnabledChanges_AllSubdevicesAreUpdated) {
1075 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001076 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001077 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
1078 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
1079 // Must add at least one mapper or the device will be ignored!
Arpit Singh8e6fb252023-04-06 11:49:17 +00001080 device->addMapper<FakeInputMapper>(eventHubIds[0], mFakePolicy->getReaderConfiguration(),
1081 AINPUT_SOURCE_KEYBOARD);
1082 device->addMapper<FakeInputMapper>(eventHubIds[1], mFakePolicy->getReaderConfiguration(),
1083 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001084 mReader->pushNextDevice(device);
1085 mReader->pushNextDevice(device);
1086 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1", deviceClass, nullptr));
1087 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[1], "fake2", deviceClass, nullptr));
1088
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001089 NotifyDeviceResetArgs resetArgs;
1090 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1091 ASSERT_EQ(deviceId, resetArgs.deviceId);
1092 ASSERT_TRUE(device->isEnabled());
1093 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
1094 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
1095
1096 disableDevice(deviceId);
1097 mReader->loopOnce();
1098
1099 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1100 ASSERT_EQ(deviceId, resetArgs.deviceId);
1101 ASSERT_FALSE(device->isEnabled());
1102 ASSERT_FALSE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
1103 ASSERT_FALSE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
1104
1105 enableDevice(deviceId);
1106 mReader->loopOnce();
1107
1108 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
1109 ASSERT_EQ(deviceId, resetArgs.deviceId);
1110 ASSERT_TRUE(device->isEnabled());
1111 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[0]));
1112 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(eventHubIds[1]));
1113}
1114
1115TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToSubdeviceMappers) {
1116 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001117 constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001118 constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
1119 // Add two subdevices to device
1120 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
1121 FakeInputMapper& mapperDevice1 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001122 device->addMapper<FakeInputMapper>(eventHubIds[0],
1123 mFakePolicy->getReaderConfiguration(),
1124 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001125 FakeInputMapper& mapperDevice2 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001126 device->addMapper<FakeInputMapper>(eventHubIds[1],
1127 mFakePolicy->getReaderConfiguration(),
1128 AINPUT_SOURCE_KEYBOARD);
Nathaniel R. Lewisc8bfa542020-02-24 14:05:11 -08001129 mReader->pushNextDevice(device);
1130 mReader->pushNextDevice(device);
1131 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "fake1", deviceClass, nullptr));
1132 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[1], "fake2", deviceClass, nullptr));
1133
1134 mapperDevice1.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
1135 mapperDevice2.setKeyCodeState(AKEYCODE_B, AKEY_STATE_DOWN);
1136
1137 ASSERT_EQ(AKEY_STATE_DOWN,
1138 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_A));
1139 ASSERT_EQ(AKEY_STATE_DOWN,
1140 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_B));
1141 ASSERT_EQ(AKEY_STATE_UNKNOWN,
1142 mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD, AKEYCODE_C));
1143}
1144
Prabir Pradhan7e186182020-11-10 13:56:45 -08001145TEST_F(InputReaderTest, ChangingPointerCaptureNotifiesInputListener) {
1146 NotifyPointerCaptureChangedArgs args;
1147
Hiroki Sato25040232024-02-22 17:21:22 +09001148 auto request = mFakePolicy->setPointerCapture(/*window=*/sp<BBinder>::make());
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001149 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE);
Prabir Pradhan7e186182020-11-10 13:56:45 -08001150 mReader->loopOnce();
1151 mFakeListener->assertNotifyCaptureWasCalled(&args);
Hiroki Sato25040232024-02-22 17:21:22 +09001152 ASSERT_TRUE(args.request.isEnable()) << "Pointer Capture should be enabled.";
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001153 ASSERT_EQ(args.request, request) << "Pointer Capture sequence number should match.";
Prabir Pradhan7e186182020-11-10 13:56:45 -08001154
Hiroki Sato25040232024-02-22 17:21:22 +09001155 mFakePolicy->setPointerCapture(/*window=*/nullptr);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001156 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE);
Prabir Pradhan7e186182020-11-10 13:56:45 -08001157 mReader->loopOnce();
1158 mFakeListener->assertNotifyCaptureWasCalled(&args);
Hiroki Sato25040232024-02-22 17:21:22 +09001159 ASSERT_FALSE(args.request.isEnable()) << "Pointer Capture should be disabled.";
Prabir Pradhan7e186182020-11-10 13:56:45 -08001160
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001161 // Verify that the Pointer Capture state is not updated when the configuration value
Prabir Pradhan7e186182020-11-10 13:56:45 -08001162 // does not change.
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001163 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::POINTER_CAPTURE);
Prabir Pradhan7e186182020-11-10 13:56:45 -08001164 mReader->loopOnce();
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001165 mFakeListener->assertNotifyCaptureWasNotCalled();
Prabir Pradhan7e186182020-11-10 13:56:45 -08001166}
1167
Prabir Pradhan018faea2024-05-08 21:52:54 +00001168TEST_F(InputReaderTest, GetLastUsedInputDeviceId) {
1169 constexpr int32_t FIRST_DEVICE_ID = END_RESERVED_ID + 1000;
1170 constexpr int32_t SECOND_DEVICE_ID = FIRST_DEVICE_ID + 1;
1171 FakeInputMapper& firstMapper =
1172 addDeviceWithFakeInputMapper(FIRST_DEVICE_ID, FIRST_DEVICE_ID, "first",
1173 InputDeviceClass::KEYBOARD, AINPUT_SOURCE_KEYBOARD,
1174 /*configuration=*/nullptr);
1175 FakeInputMapper& secondMapper =
1176 addDeviceWithFakeInputMapper(SECOND_DEVICE_ID, SECOND_DEVICE_ID, "second",
1177 InputDeviceClass::TOUCH_MT, AINPUT_SOURCE_STYLUS,
1178 /*configuration=*/nullptr);
1179
1180 ASSERT_EQ(ReservedInputDeviceId::INVALID_INPUT_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1181
1182 // Start a new key gesture from the first device
1183 firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
1184 .deviceId(FIRST_DEVICE_ID)
1185 .build()});
1186 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
1187 mReader->loopOnce();
1188 ASSERT_EQ(firstMapper.getDeviceId(), mReader->getLastUsedInputDeviceId());
1189
1190 // Start a new touch gesture from the second device
1191 secondMapper.setProcessResult(
1192 {MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
1193 .deviceId(SECOND_DEVICE_ID)
1194 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER))
1195 .build()});
1196 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
1197 mReader->loopOnce();
1198 ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1199
1200 // Releasing the key is not a new gesture, so it does not update the last used device
1201 firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
1202 .deviceId(FIRST_DEVICE_ID)
1203 .build()});
1204 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
1205 mReader->loopOnce();
1206 ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1207
1208 // But pressing a new key does start a new gesture
1209 firstMapper.setProcessResult({KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
1210 .deviceId(FIRST_DEVICE_ID)
1211 .build()});
1212 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, FIRST_DEVICE_ID, 0, 0, 0);
1213 mReader->loopOnce();
1214 ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1215
1216 // Moving or ending a touch gesture does not update the last used device
1217 secondMapper.setProcessResult(
1218 {MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
1219 .deviceId(SECOND_DEVICE_ID)
1220 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
1221 .build()});
1222 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
1223 mReader->loopOnce();
1224 ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1225 secondMapper.setProcessResult({MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
1226 .deviceId(SECOND_DEVICE_ID)
1227 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
1228 .build()});
1229 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
1230 mReader->loopOnce();
1231 ASSERT_EQ(FIRST_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1232
1233 // Starting a new hover gesture updates the last used device
1234 secondMapper.setProcessResult(
1235 {MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1236 .deviceId(SECOND_DEVICE_ID)
1237 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS))
1238 .build()});
1239 mFakeEventHub->enqueueEvent(ARBITRARY_TIME, ARBITRARY_TIME, SECOND_DEVICE_ID, 0, 0, 0);
1240 mReader->loopOnce();
1241 ASSERT_EQ(SECOND_DEVICE_ID, mReader->getLastUsedInputDeviceId());
1242}
1243
Chris Ye87143712020-11-10 05:05:58 +00001244class FakeVibratorInputMapper : public FakeInputMapper {
1245public:
Arpit Singh8e6fb252023-04-06 11:49:17 +00001246 FakeVibratorInputMapper(InputDeviceContext& deviceContext,
1247 const InputReaderConfiguration& readerConfig, uint32_t sources)
1248 : FakeInputMapper(deviceContext, readerConfig, sources) {}
Chris Ye87143712020-11-10 05:05:58 +00001249
1250 std::vector<int32_t> getVibratorIds() override { return getDeviceContext().getVibratorIds(); }
1251};
1252
1253TEST_F(InputReaderTest, VibratorGetVibratorIds) {
1254 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001255 ftl::Flags<InputDeviceClass> deviceClass =
1256 InputDeviceClass::KEYBOARD | InputDeviceClass::VIBRATOR;
Chris Ye87143712020-11-10 05:05:58 +00001257 constexpr int32_t eventHubId = 1;
1258 const char* DEVICE_LOCATION = "BLUETOOTH";
1259 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
1260 FakeVibratorInputMapper& mapper =
Arpit Singh8e6fb252023-04-06 11:49:17 +00001261 device->addMapper<FakeVibratorInputMapper>(eventHubId,
1262 mFakePolicy->getReaderConfiguration(),
1263 AINPUT_SOURCE_KEYBOARD);
Chris Ye87143712020-11-10 05:05:58 +00001264 mReader->pushNextDevice(device);
1265
1266 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1267 ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
1268
1269 ASSERT_EQ(mapper.getVibratorIds().size(), 2U);
1270 ASSERT_EQ(mReader->getVibratorIds(deviceId).size(), 2U);
1271}
1272
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001273// --- FakePeripheralController ---
Kim Low03ea0352020-11-06 12:45:07 -08001274
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001275class FakePeripheralController : public PeripheralControllerInterface {
Chris Yee2b1e5c2021-03-10 22:45:12 -08001276public:
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001277 FakePeripheralController(InputDeviceContext& deviceContext) : mDeviceContext(deviceContext) {}
Chris Yee2b1e5c2021-03-10 22:45:12 -08001278
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001279 ~FakePeripheralController() override {}
Chris Yee2b1e5c2021-03-10 22:45:12 -08001280
Andy Chenf9f1a022022-08-29 20:07:10 -04001281 int32_t getEventHubId() const { return getDeviceContext().getEventHubId(); }
1282
Chris Yee2b1e5c2021-03-10 22:45:12 -08001283 void populateDeviceInfo(InputDeviceInfo* deviceInfo) override {}
1284
1285 void dump(std::string& dump) override {}
1286
1287 std::optional<int32_t> getBatteryCapacity(int32_t batteryId) override {
1288 return getDeviceContext().getBatteryCapacity(batteryId);
Kim Low03ea0352020-11-06 12:45:07 -08001289 }
1290
Chris Yee2b1e5c2021-03-10 22:45:12 -08001291 std::optional<int32_t> getBatteryStatus(int32_t batteryId) override {
1292 return getDeviceContext().getBatteryStatus(batteryId);
Kim Low03ea0352020-11-06 12:45:07 -08001293 }
Chris Ye3fdbfef2021-01-06 18:45:18 -08001294
1295 bool setLightColor(int32_t lightId, int32_t color) override {
1296 getDeviceContext().setLightBrightness(lightId, color >> 24);
1297 return true;
1298 }
1299
1300 std::optional<int32_t> getLightColor(int32_t lightId) override {
1301 std::optional<int32_t> result = getDeviceContext().getLightBrightness(lightId);
1302 if (!result.has_value()) {
1303 return std::nullopt;
1304 }
1305 return result.value() << 24;
1306 }
Chris Yee2b1e5c2021-03-10 22:45:12 -08001307
1308 bool setLightPlayerId(int32_t lightId, int32_t playerId) override { return true; }
1309
1310 std::optional<int32_t> getLightPlayerId(int32_t lightId) override { return std::nullopt; }
1311
1312private:
1313 InputDeviceContext& mDeviceContext;
1314 inline int32_t getDeviceId() { return mDeviceContext.getId(); }
1315 inline InputDeviceContext& getDeviceContext() { return mDeviceContext; }
Andy Chenf9f1a022022-08-29 20:07:10 -04001316 inline InputDeviceContext& getDeviceContext() const { return mDeviceContext; }
Chris Ye3fdbfef2021-01-06 18:45:18 -08001317};
1318
Chris Yee2b1e5c2021-03-10 22:45:12 -08001319TEST_F(InputReaderTest, BatteryGetCapacity) {
1320 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001321 ftl::Flags<InputDeviceClass> deviceClass =
1322 InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
Chris Yee2b1e5c2021-03-10 22:45:12 -08001323 constexpr int32_t eventHubId = 1;
1324 const char* DEVICE_LOCATION = "BLUETOOTH";
1325 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001326 FakePeripheralController& controller =
1327 device->addController<FakePeripheralController>(eventHubId);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001328 mReader->pushNextDevice(device);
1329
1330 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1331
Harry Cuttsa5b71292022-11-28 12:56:17 +00001332 ASSERT_EQ(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY),
1333 FakeEventHub::BATTERY_CAPACITY);
1334 ASSERT_EQ(mReader->getBatteryCapacity(deviceId), FakeEventHub::BATTERY_CAPACITY);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001335}
1336
1337TEST_F(InputReaderTest, BatteryGetStatus) {
1338 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001339 ftl::Flags<InputDeviceClass> deviceClass =
1340 InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
Chris Yee2b1e5c2021-03-10 22:45:12 -08001341 constexpr int32_t eventHubId = 1;
1342 const char* DEVICE_LOCATION = "BLUETOOTH";
1343 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001344 FakePeripheralController& controller =
1345 device->addController<FakePeripheralController>(eventHubId);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001346 mReader->pushNextDevice(device);
1347
1348 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1349
Harry Cuttsa5b71292022-11-28 12:56:17 +00001350 ASSERT_EQ(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY),
1351 FakeEventHub::BATTERY_STATUS);
1352 ASSERT_EQ(mReader->getBatteryStatus(deviceId), FakeEventHub::BATTERY_STATUS);
Chris Yee2b1e5c2021-03-10 22:45:12 -08001353}
1354
Prabir Pradhane287ecd2022-09-07 21:18:05 +00001355TEST_F(InputReaderTest, BatteryGetDevicePath) {
1356 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
1357 ftl::Flags<InputDeviceClass> deviceClass =
1358 InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
1359 constexpr int32_t eventHubId = 1;
1360 const char* DEVICE_LOCATION = "BLUETOOTH";
1361 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
1362 device->addController<FakePeripheralController>(eventHubId);
1363 mReader->pushNextDevice(device);
1364
1365 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
1366
Harry Cuttsa5b71292022-11-28 12:56:17 +00001367 ASSERT_EQ(mReader->getBatteryDevicePath(deviceId), FakeEventHub::BATTERY_DEVPATH);
Prabir Pradhane287ecd2022-09-07 21:18:05 +00001368}
1369
Chris Ye3fdbfef2021-01-06 18:45:18 -08001370TEST_F(InputReaderTest, LightGetColor) {
1371 constexpr int32_t deviceId = END_RESERVED_ID + 1000;
Dominik Laskowski2f01d772022-03-23 16:01:29 -07001372 ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::LIGHT;
Chris Ye3fdbfef2021-01-06 18:45:18 -08001373 constexpr int32_t eventHubId = 1;
1374 const char* DEVICE_LOCATION = "BLUETOOTH";
1375 std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
Chris Ye1dd2e5c2021-04-04 23:12:41 -07001376 FakePeripheralController& controller =
1377 device->addController<FakePeripheralController>(eventHubId);
Chris Ye3fdbfef2021-01-06 18:45:18 -08001378 mReader->pushNextDevice(device);
1379 RawLightInfo info = {.id = 1,
1380 .name = "Mono",
1381 .maxBrightness = 255,
1382 .flags = InputLightClass::BRIGHTNESS,
1383 .path = ""};
Harry Cutts33476232023-01-30 19:57:29 +00001384 mFakeEventHub->addRawLightInfo(/*rawId=*/1, std::move(info));
1385 mFakeEventHub->fakeLightBrightness(/*rawId=*/1, 0x55);
Chris Ye3fdbfef2021-01-06 18:45:18 -08001386
1387 ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
Chris Ye3fdbfef2021-01-06 18:45:18 -08001388
Harry Cutts33476232023-01-30 19:57:29 +00001389 ASSERT_TRUE(controller.setLightColor(/*lightId=*/1, LIGHT_BRIGHTNESS));
1390 ASSERT_EQ(controller.getLightColor(/*lightId=*/1), LIGHT_BRIGHTNESS);
1391 ASSERT_TRUE(mReader->setLightColor(deviceId, /*lightId=*/1, LIGHT_BRIGHTNESS));
1392 ASSERT_EQ(mReader->getLightColor(deviceId, /*lightId=*/1), LIGHT_BRIGHTNESS);
Chris Ye3fdbfef2021-01-06 18:45:18 -08001393}
1394
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001395// --- InputReaderIntegrationTest ---
1396
1397// These tests create and interact with the InputReader only through its interface.
1398// The InputReader is started during SetUp(), which starts its processing in its own
1399// thread. The tests use linux uinput to emulate input devices.
1400// NOTE: Interacting with the physical device while these tests are running may cause
1401// the tests to fail.
1402class InputReaderIntegrationTest : public testing::Test {
1403protected:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001404 std::unique_ptr<TestInputListener> mTestListener;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001405 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001406 std::unique_ptr<InputReaderInterface> mReader;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001407
Prabir Pradhanafb7d612024-01-08 22:45:24 +00001408 constexpr static auto EVENT_HAPPENED_TIMEOUT = 2000ms;
1409 constexpr static auto EVENT_DID_NOT_HAPPEN_TIMEOUT = 30ms;
1410
Chris Yea52ade12020-08-27 16:49:20 -07001411 void SetUp() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001412#if !defined(__ANDROID__)
1413 GTEST_SKIP();
1414#endif
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001415 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001416
Arpit Singh440bf652023-08-09 09:23:43 +00001417 setupInputReader();
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001418 }
1419
Chris Yea52ade12020-08-27 16:49:20 -07001420 void TearDown() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001421#if !defined(__ANDROID__)
1422 return;
1423#endif
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001424 ASSERT_EQ(mReader->stop(), OK);
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001425 mReader.reset();
1426 mTestListener.reset();
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001427 mFakePolicy.clear();
1428 }
Prabir Pradhanda20b172022-09-26 17:01:18 +00001429
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001430 std::optional<InputDeviceInfo> waitForDevice(const std::string& deviceName) {
1431 std::chrono::time_point start = std::chrono::steady_clock::now();
1432 while (true) {
1433 const std::vector<InputDeviceInfo> inputDevices = mFakePolicy->getInputDevices();
1434 const auto& it = std::find_if(inputDevices.begin(), inputDevices.end(),
1435 [&deviceName](const InputDeviceInfo& info) {
1436 return info.getIdentifier().name == deviceName;
1437 });
1438 if (it != inputDevices.end()) {
1439 return std::make_optional(*it);
1440 }
1441 std::this_thread::sleep_for(1ms);
1442 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
1443 if (elapsed > 5s) {
1444 return {};
1445 }
1446 }
Prabir Pradhanda20b172022-09-26 17:01:18 +00001447 }
Arpit Singh440bf652023-08-09 09:23:43 +00001448
1449 void setupInputReader() {
Prabir Pradhanafb7d612024-01-08 22:45:24 +00001450 mTestListener = std::make_unique<TestInputListener>(EVENT_HAPPENED_TIMEOUT,
1451 EVENT_DID_NOT_HAPPEN_TIMEOUT);
Arpit Singh440bf652023-08-09 09:23:43 +00001452
1453 mReader = std::make_unique<InputReader>(std::make_shared<EventHub>(), mFakePolicy,
1454 *mTestListener);
1455 ASSERT_EQ(mReader->start(), OK);
1456
1457 // Since this test is run on a real device, all the input devices connected
1458 // to the test device will show up in mReader. We wait for those input devices to
1459 // show up before beginning the tests.
Arpit Singh440bf652023-08-09 09:23:43 +00001460 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyInputDevicesChangedWasCalled());
Vaibhav Devmuraric109d812024-07-10 14:21:27 +00001461 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Arpit Singh440bf652023-08-09 09:23:43 +00001462 }
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001463};
1464
1465TEST_F(InputReaderIntegrationTest, TestInvalidDevice) {
1466 // An invalid input device that is only used for this test.
1467 class InvalidUinputDevice : public UinputDevice {
1468 public:
Harry Cutts33476232023-01-30 19:57:29 +00001469 InvalidUinputDevice() : UinputDevice("Invalid Device", /*productId=*/99) {}
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001470
1471 private:
1472 void configureDevice(int fd, uinput_user_dev* device) override {}
1473 };
1474
1475 const size_t numDevices = mFakePolicy->getInputDevices().size();
1476
1477 // UinputDevice does not set any event or key bits, so InputReader should not
1478 // consider it as a valid device.
1479 std::unique_ptr<UinputDevice> invalidDevice = createUinputDevice<InvalidUinputDevice>();
1480 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesNotChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001481 ASSERT_EQ(numDevices, mFakePolicy->getInputDevices().size());
1482
1483 invalidDevice.reset();
1484 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesNotChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001485 ASSERT_EQ(numDevices, mFakePolicy->getInputDevices().size());
1486}
1487
1488TEST_F(InputReaderIntegrationTest, AddNewDevice) {
1489 const size_t initialNumDevices = mFakePolicy->getInputDevices().size();
1490
1491 std::unique_ptr<UinputHomeKey> keyboard = createUinputDevice<UinputHomeKey>();
1492 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001493 ASSERT_EQ(initialNumDevices + 1, mFakePolicy->getInputDevices().size());
1494
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001495 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001496 ASSERT_TRUE(device.has_value());
1497 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, device->getKeyboardType());
1498 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources());
1499 ASSERT_EQ(0U, device->getMotionRanges().size());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001500
1501 keyboard.reset();
1502 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001503 ASSERT_EQ(initialNumDevices, mFakePolicy->getInputDevices().size());
1504}
1505
1506TEST_F(InputReaderIntegrationTest, SendsEventsToInputListener) {
1507 std::unique_ptr<UinputHomeKey> keyboard = createUinputDevice<UinputHomeKey>();
1508 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1509
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001510 NotifyKeyArgs keyArgs;
1511 keyboard->pressAndReleaseHomeKey();
1512 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs));
1513 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001514 ASSERT_LE(keyArgs.eventTime, keyArgs.readTime);
Liana Kazanova5b8217b2024-07-18 17:44:51 +00001515
1516 int32_t prevId = keyArgs.id;
1517 nsecs_t prevTimestamp = keyArgs.eventTime;
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001518
1519 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs));
1520 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
Garfield Tan1c7bc862020-01-28 13:24:04 -08001521 ASSERT_NE(prevId, keyArgs.id);
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001522 ASSERT_LE(prevTimestamp, keyArgs.eventTime);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001523 ASSERT_LE(keyArgs.eventTime, keyArgs.readTime);
Prabir Pradhan1aed8582019-12-30 11:46:51 -08001524}
Michael Wrightd02c5b62014-02-10 15:10:22 -08001525
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001526TEST_F(InputReaderIntegrationTest, ExternalStylusesButtons) {
1527 std::unique_ptr<UinputExternalStylus> stylus = createUinputDevice<UinputExternalStylus>();
1528 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1529
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001530 const auto device = waitForDevice(stylus->getName());
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001531 ASSERT_TRUE(device.has_value());
1532
Prabir Pradhana3621852022-10-14 18:57:23 +00001533 // An external stylus with buttons should also be recognized as a keyboard.
1534 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_STYLUS, device->getSources())
Prabir Pradhane1a41a82022-10-14 18:06:50 +00001535 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1536 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, device->getKeyboardType());
1537
1538 const auto DOWN =
1539 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD));
1540 const auto UP = AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD));
1541
1542 stylus->pressAndReleaseKey(BTN_STYLUS);
1543 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1544 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
1545 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1546 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY))));
1547
1548 stylus->pressAndReleaseKey(BTN_STYLUS2);
1549 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1550 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_SECONDARY))));
1551 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1552 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_SECONDARY))));
1553
1554 stylus->pressAndReleaseKey(BTN_STYLUS3);
1555 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1556 AllOf(DOWN, WithKeyCode(AKEYCODE_STYLUS_BUTTON_TERTIARY))));
1557 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(
1558 AllOf(UP, WithKeyCode(AKEYCODE_STYLUS_BUTTON_TERTIARY))));
1559}
1560
Prabir Pradhan3c28b942023-08-18 20:02:01 +00001561TEST_F(InputReaderIntegrationTest, KeyboardWithStylusButtons) {
1562 std::unique_ptr<UinputKeyboard> keyboard =
1563 createUinputDevice<UinputKeyboard>("KeyboardWithStylusButtons", /*productId=*/99,
1564 std::initializer_list<int>{KEY_Q, KEY_W, KEY_E,
1565 KEY_R, KEY_T, KEY_Y,
1566 BTN_STYLUS, BTN_STYLUS2,
1567 BTN_STYLUS3});
1568 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1569
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001570 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhan3c28b942023-08-18 20:02:01 +00001571 ASSERT_TRUE(device.has_value());
1572
1573 // An alphabetical keyboard that reports stylus buttons should not be recognized as a stylus.
1574 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources())
1575 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1576 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, device->getKeyboardType());
1577}
1578
Prabir Pradhan37a819b2023-08-22 23:20:16 +00001579TEST_F(InputReaderIntegrationTest, HidUsageKeyboardIsNotAStylus) {
1580 // Create a Uinput keyboard that simulates a keyboard that can report HID usage codes. The
1581 // hid-input driver reports HID usage codes using the value for EV_MSC MSC_SCAN event.
1582 std::unique_ptr<UinputKeyboardWithHidUsage> keyboard =
1583 createUinputDevice<UinputKeyboardWithHidUsage>(
1584 std::initializer_list<int>{KEY_VOLUMEUP, KEY_VOLUMEDOWN});
1585 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1586
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001587 const auto device = waitForDevice(keyboard->getName());
Prabir Pradhan37a819b2023-08-22 23:20:16 +00001588 ASSERT_TRUE(device.has_value());
1589
1590 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources())
1591 << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
1592
1593 // If a device supports reporting HID usage codes, it shouldn't automatically support
1594 // stylus keys.
1595 const std::vector<int> keycodes{AKEYCODE_STYLUS_BUTTON_PRIMARY};
1596 uint8_t outFlags[] = {0};
1597 ASSERT_TRUE(mReader->hasKeys(device->getId(), AINPUT_SOURCE_KEYBOARD, keycodes, outFlags));
1598 ASSERT_EQ(0, outFlags[0]) << "Keyboard should not have stylus button";
1599}
1600
Siarhei Vishniakoua0d2b802020-05-13 14:00:31 -07001601/**
1602 * The Steam controller sends BTN_GEAR_DOWN and BTN_GEAR_UP for the two "paddle" buttons
1603 * on the back. In this test, we make sure that BTN_GEAR_DOWN / BTN_WHEEL and BTN_GEAR_UP
1604 * are passed to the listener.
1605 */
1606static_assert(BTN_GEAR_DOWN == BTN_WHEEL);
1607TEST_F(InputReaderIntegrationTest, SendsGearDownAndUpToInputListener) {
1608 std::unique_ptr<UinputSteamController> controller = createUinputDevice<UinputSteamController>();
1609 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1610 NotifyKeyArgs keyArgs;
1611
1612 controller->pressAndReleaseKey(BTN_GEAR_DOWN);
1613 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_DOWN
1614 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_UP
1615 ASSERT_EQ(BTN_GEAR_DOWN, keyArgs.scanCode);
1616
1617 controller->pressAndReleaseKey(BTN_GEAR_UP);
1618 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_DOWN
1619 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs)); // ACTION_UP
1620 ASSERT_EQ(BTN_GEAR_UP, keyArgs.scanCode);
1621}
1622
Prabir Pradhan484d55a2022-10-14 23:17:16 +00001623// --- TouchIntegrationTest ---
1624
Arpit Singh440bf652023-08-09 09:23:43 +00001625class BaseTouchIntegrationTest : public InputReaderIntegrationTest {
Arthur Hungaab25622020-01-16 11:22:11 +08001626protected:
Arthur Hungaab25622020-01-16 11:22:11 +08001627 const std::string UNIQUE_ID = "local:0";
1628
Chris Yea52ade12020-08-27 16:49:20 -07001629 void SetUp() override {
Siarhei Vishniakou31977182022-09-30 08:51:23 -07001630#if !defined(__ANDROID__)
1631 GTEST_SKIP();
1632#endif
Arthur Hungaab25622020-01-16 11:22:11 +08001633 InputReaderIntegrationTest::SetUp();
1634 // At least add an internal display.
Michael Wrighta9cf4192022-12-01 23:46:39 +00001635 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
1636 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Arthur Hungaab25622020-01-16 11:22:11 +08001637
1638 mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT));
1639 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001640 const auto info = waitForDevice(mDevice->getName());
Prabir Pradhanda20b172022-09-26 17:01:18 +00001641 ASSERT_TRUE(info);
1642 mDeviceInfo = *info;
Arthur Hungaab25622020-01-16 11:22:11 +08001643 }
1644
Linnan Li13bf76a2024-05-05 19:18:02 +08001645 void setDisplayInfoAndReconfigure(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
Michael Wrighta9cf4192022-12-01 23:46:39 +00001646 ui::Rotation orientation, const std::string& uniqueId,
Arthur Hungaab25622020-01-16 11:22:11 +08001647 std::optional<uint8_t> physicalPort,
1648 ViewportType viewportType) {
Harry Cutts33476232023-01-30 19:57:29 +00001649 mFakePolicy->addDisplayViewport(displayId, width, height, orientation, /*isActive=*/true,
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00001650 uniqueId, physicalPort, viewportType);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00001651 mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hungaab25622020-01-16 11:22:11 +08001652 }
1653
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001654 void assertReceivedMotion(int32_t action, const std::vector<Point>& points) {
1655 NotifyMotionArgs args;
1656 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1657 EXPECT_EQ(action, args.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07001658 ASSERT_EQ(points.size(), args.getPointerCount());
1659 for (size_t i = 0; i < args.getPointerCount(); i++) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001660 EXPECT_EQ(points[i].x, args.pointerCoords[i].getX());
1661 EXPECT_EQ(points[i].y, args.pointerCoords[i].getY());
1662 }
1663 }
1664
Arthur Hungaab25622020-01-16 11:22:11 +08001665 std::unique_ptr<UinputTouchScreen> mDevice;
Prabir Pradhanda20b172022-09-26 17:01:18 +00001666 InputDeviceInfo mDeviceInfo;
Arthur Hungaab25622020-01-16 11:22:11 +08001667};
1668
Arpit Singh440bf652023-08-09 09:23:43 +00001669enum class TouchIntegrationTestDisplays { DISPLAY_INTERNAL, DISPLAY_INPUT_PORT, DISPLAY_UNIQUE_ID };
1670
1671class TouchIntegrationTest : public BaseTouchIntegrationTest,
1672 public testing::WithParamInterface<TouchIntegrationTestDisplays> {
1673protected:
1674 static constexpr std::optional<uint8_t> DISPLAY_PORT = 0;
1675 const std::string INPUT_PORT = "uinput_touch/input0";
1676
1677 void SetUp() override {
1678#if !defined(__ANDROID__)
1679 GTEST_SKIP();
1680#endif
1681 if (GetParam() == TouchIntegrationTestDisplays::DISPLAY_INTERNAL) {
1682 BaseTouchIntegrationTest::SetUp();
1683 return;
1684 }
1685
1686 // setup policy with a input-port or UniqueId association to the display
1687 bool isInputPortAssociation =
1688 GetParam() == TouchIntegrationTestDisplays::DISPLAY_INPUT_PORT;
1689
1690 mFakePolicy = sp<FakeInputReaderPolicy>::make();
1691 if (isInputPortAssociation) {
1692 mFakePolicy->addInputPortAssociation(INPUT_PORT, DISPLAY_PORT.value());
1693 } else {
1694 mFakePolicy->addInputUniqueIdAssociation(INPUT_PORT, UNIQUE_ID);
1695 }
Arpit Singh440bf652023-08-09 09:23:43 +00001696
1697 InputReaderIntegrationTest::setupInputReader();
1698
1699 mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT),
1700 INPUT_PORT);
1701 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
1702
1703 // Add a display linked to a physical port or UniqueId.
1704 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
1705 UNIQUE_ID, isInputPortAssociation ? DISPLAY_PORT : NO_PORT,
1706 ViewportType::INTERNAL);
1707 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08001708 const auto info = waitForDevice(mDevice->getName());
Arpit Singh440bf652023-08-09 09:23:43 +00001709 ASSERT_TRUE(info);
1710 mDeviceInfo = *info;
1711 }
1712};
1713
1714TEST_P(TouchIntegrationTest, MultiTouchDeviceSource) {
Prabir Pradhanf9a41282022-10-25 17:15:50 +00001715 // The UinputTouchScreen is an MT device that supports MT_TOOL_TYPE and also supports stylus
1716 // buttons. It should show up as a touchscreen, stylus, and keyboard (for reporting button
1717 // presses).
1718 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD,
1719 mDeviceInfo.getSources());
1720}
1721
Arpit Singh440bf652023-08-09 09:23:43 +00001722TEST_P(TouchIntegrationTest, InputEvent_ProcessSingleTouch) {
Arthur Hungaab25622020-01-16 11:22:11 +08001723 NotifyMotionArgs args;
1724 const Point centerPoint = mDevice->getCenterPoint();
1725
1726 // ACTION_DOWN
Arthur Hung9ad18942021-06-19 02:04:46 +00001727 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001728 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001729 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001730 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1731 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1732
1733 // ACTION_MOVE
1734 mDevice->sendMove(centerPoint + Point(1, 1));
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001735 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001736 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1737 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1738
1739 // ACTION_UP
1740 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001741 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001742 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1743 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
1744}
1745
Arpit Singh440bf652023-08-09 09:23:43 +00001746TEST_P(TouchIntegrationTest, InputEvent_ProcessMultiTouch) {
Arthur Hungaab25622020-01-16 11:22:11 +08001747 NotifyMotionArgs args;
1748 const Point centerPoint = mDevice->getCenterPoint();
1749
1750 // ACTION_DOWN
Arthur Hung9ad18942021-06-19 02:04:46 +00001751 mDevice->sendSlot(FIRST_SLOT);
1752 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001753 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001754 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001755 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1756 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1757
1758 // ACTION_POINTER_DOWN (Second slot)
1759 const Point secondPoint = centerPoint + Point(100, 100);
1760 mDevice->sendSlot(SECOND_SLOT);
1761 mDevice->sendTrackingId(SECOND_TRACKING_ID);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001762 mDevice->sendDown(secondPoint);
1763 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001764 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001765 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001766
1767 // ACTION_MOVE (Second slot)
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001768 mDevice->sendMove(secondPoint + Point(1, 1));
1769 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001770 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1771 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1772
1773 // ACTION_POINTER_UP (Second slot)
arthurhungcc7f9802020-04-30 17:55:40 +08001774 mDevice->sendPointerUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001775 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001776 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001777 ASSERT_EQ(ACTION_POINTER_1_UP, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001778
1779 // ACTION_UP
1780 mDevice->sendSlot(FIRST_SLOT);
1781 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001782 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001783 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1784 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
1785}
1786
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001787/**
1788 * What happens when a pointer goes up while another pointer moves in the same frame? Are POINTER_UP
1789 * events guaranteed to contain the same data as a preceding MOVE, or can they contain different
1790 * data?
1791 * In this test, we try to send a change in coordinates in Pointer 0 in the same frame as the
1792 * liftoff of Pointer 1. We check that POINTER_UP event is generated first, and the MOVE event
1793 * for Pointer 0 only is generated after.
1794 * Suppose we are only interested in learning the movement of Pointer 0. If we only observe MOVE
1795 * events, we will not miss any information.
1796 * Even though the Pointer 1 up event contains updated Pointer 0 coordinates, there is another MOVE
1797 * event generated afterwards that contains the newest movement of pointer 0.
1798 * This is important for palm rejection. If there is a subsequent InputListener stage that detects
1799 * palms, and wants to cancel Pointer 1, then it is safe to simply drop POINTER_1_UP event without
1800 * losing information about non-palm pointers.
1801 */
Arpit Singh440bf652023-08-09 09:23:43 +00001802TEST_P(TouchIntegrationTest, MultiTouch_PointerMoveAndSecondPointerUp) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001803 NotifyMotionArgs args;
1804 const Point centerPoint = mDevice->getCenterPoint();
1805
1806 // ACTION_DOWN
1807 mDevice->sendSlot(FIRST_SLOT);
1808 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1809 mDevice->sendDown(centerPoint);
1810 mDevice->sendSync();
1811 assertReceivedMotion(AMOTION_EVENT_ACTION_DOWN, {centerPoint});
1812
1813 // ACTION_POINTER_DOWN (Second slot)
1814 const Point secondPoint = centerPoint + Point(100, 100);
1815 mDevice->sendSlot(SECOND_SLOT);
1816 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1817 mDevice->sendDown(secondPoint);
1818 mDevice->sendSync();
1819 assertReceivedMotion(ACTION_POINTER_1_DOWN, {centerPoint, secondPoint});
1820
1821 // ACTION_MOVE (First slot)
1822 mDevice->sendSlot(FIRST_SLOT);
1823 mDevice->sendMove(centerPoint + Point(5, 5));
1824 // ACTION_POINTER_UP (Second slot)
1825 mDevice->sendSlot(SECOND_SLOT);
1826 mDevice->sendPointerUp();
1827 // Send a single sync for the above 2 pointer updates
1828 mDevice->sendSync();
1829
1830 // First, we should get POINTER_UP for the second pointer
1831 assertReceivedMotion(ACTION_POINTER_1_UP,
1832 {/*first pointer */ centerPoint + Point(5, 5),
1833 /*second pointer*/ secondPoint});
1834
1835 // Next, the MOVE event for the first pointer
1836 assertReceivedMotion(AMOTION_EVENT_ACTION_MOVE, {centerPoint + Point(5, 5)});
1837}
1838
1839/**
1840 * Similar scenario as above. The difference is that when the second pointer goes up, it will first
1841 * move, and then it will go up, all in the same frame.
1842 * In this scenario, the movement of the second pointer just prior to liftoff is ignored, and never
1843 * gets sent to the listener.
1844 */
Arpit Singh440bf652023-08-09 09:23:43 +00001845TEST_P(TouchIntegrationTest, MultiTouch_PointerMoveAndSecondPointerMoveAndUp) {
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001846 NotifyMotionArgs args;
1847 const Point centerPoint = mDevice->getCenterPoint();
1848
1849 // ACTION_DOWN
1850 mDevice->sendSlot(FIRST_SLOT);
1851 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1852 mDevice->sendDown(centerPoint);
1853 mDevice->sendSync();
1854 assertReceivedMotion(AMOTION_EVENT_ACTION_DOWN, {centerPoint});
1855
1856 // ACTION_POINTER_DOWN (Second slot)
1857 const Point secondPoint = centerPoint + Point(100, 100);
1858 mDevice->sendSlot(SECOND_SLOT);
1859 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1860 mDevice->sendDown(secondPoint);
1861 mDevice->sendSync();
1862 assertReceivedMotion(ACTION_POINTER_1_DOWN, {centerPoint, secondPoint});
1863
1864 // ACTION_MOVE (First slot)
1865 mDevice->sendSlot(FIRST_SLOT);
1866 mDevice->sendMove(centerPoint + Point(5, 5));
1867 // ACTION_POINTER_UP (Second slot)
1868 mDevice->sendSlot(SECOND_SLOT);
1869 mDevice->sendMove(secondPoint + Point(6, 6));
1870 mDevice->sendPointerUp();
1871 // Send a single sync for the above 2 pointer updates
1872 mDevice->sendSync();
1873
1874 // First, we should get POINTER_UP for the second pointer
1875 // The movement of the second pointer during the liftoff frame is ignored.
1876 // The coordinates 'secondPoint + Point(6, 6)' are never sent to the listener.
1877 assertReceivedMotion(ACTION_POINTER_1_UP,
1878 {/*first pointer */ centerPoint + Point(5, 5),
1879 /*second pointer*/ secondPoint});
1880
1881 // Next, the MOVE event for the first pointer
1882 assertReceivedMotion(AMOTION_EVENT_ACTION_MOVE, {centerPoint + Point(5, 5)});
1883}
1884
Arpit Singh440bf652023-08-09 09:23:43 +00001885TEST_P(TouchIntegrationTest, InputEvent_ProcessPalm) {
Arthur Hungaab25622020-01-16 11:22:11 +08001886 NotifyMotionArgs args;
1887 const Point centerPoint = mDevice->getCenterPoint();
1888
1889 // ACTION_DOWN
arthurhungcc7f9802020-04-30 17:55:40 +08001890 mDevice->sendSlot(FIRST_SLOT);
1891 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Arthur Hungaab25622020-01-16 11:22:11 +08001892 mDevice->sendDown(centerPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001893 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001894 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1895 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
1896
arthurhungcc7f9802020-04-30 17:55:40 +08001897 // ACTION_POINTER_DOWN (second slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001898 const Point secondPoint = centerPoint + Point(100, 100);
1899 mDevice->sendSlot(SECOND_SLOT);
1900 mDevice->sendTrackingId(SECOND_TRACKING_ID);
1901 mDevice->sendDown(secondPoint);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001902 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001903 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001904 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001905
arthurhungcc7f9802020-04-30 17:55:40 +08001906 // ACTION_MOVE (second slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001907 mDevice->sendMove(secondPoint + Point(1, 1));
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001908 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001909 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1910 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
1911
arthurhungcc7f9802020-04-30 17:55:40 +08001912 // Send MT_TOOL_PALM (second slot), which indicates that the touch IC has determined this to be
1913 // a palm event.
1914 // Expect to receive the ACTION_POINTER_UP with cancel flag.
Arthur Hungaab25622020-01-16 11:22:11 +08001915 mDevice->sendToolType(MT_TOOL_PALM);
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001916 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001917 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08001918 ASSERT_EQ(ACTION_POINTER_1_UP, args.action);
arthurhungcc7f9802020-04-30 17:55:40 +08001919 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, args.flags);
Arthur Hungaab25622020-01-16 11:22:11 +08001920
arthurhungcc7f9802020-04-30 17:55:40 +08001921 // Send up to second slot, expect first slot send moving.
1922 mDevice->sendPointerUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001923 mDevice->sendSync();
arthurhungcc7f9802020-04-30 17:55:40 +08001924 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1925 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001926
arthurhungcc7f9802020-04-30 17:55:40 +08001927 // Send ACTION_UP (first slot)
Arthur Hungaab25622020-01-16 11:22:11 +08001928 mDevice->sendSlot(FIRST_SLOT);
1929 mDevice->sendUp();
Siarhei Vishniakoufd97e9d2022-01-04 16:59:04 -08001930 mDevice->sendSync();
Arthur Hungaab25622020-01-16 11:22:11 +08001931
arthurhungcc7f9802020-04-30 17:55:40 +08001932 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
1933 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
Arthur Hungaab25622020-01-16 11:22:11 +08001934}
1935
Prabir Pradhanc09ec6d2023-08-14 22:31:43 +00001936/**
1937 * Some drivers historically have reported axis values outside of the range specified in the
1938 * evdev axis info. Ensure we don't crash when this happens. For example, a driver may report a
1939 * pressure value greater than the reported maximum, since it unclear what specific meaning the
1940 * maximum value for pressure has (beyond the maximum value that can be produced by a sensor),
1941 * and no units for pressure (resolution) is specified by the evdev documentation.
1942 */
1943TEST_P(TouchIntegrationTest, AcceptsAxisValuesOutsideReportedRange) {
1944 const Point centerPoint = mDevice->getCenterPoint();
1945
1946 // Down with pressure outside the reported range
1947 mDevice->sendSlot(FIRST_SLOT);
1948 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1949 mDevice->sendDown(centerPoint);
1950 mDevice->sendPressure(UinputTouchScreen::RAW_PRESSURE_MAX + 2);
1951 mDevice->sendSync();
1952 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1953 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
1954
1955 // Move to a point outside the reported range
1956 mDevice->sendMove(Point(DISPLAY_WIDTH, DISPLAY_HEIGHT) + Point(1, 1));
1957 mDevice->sendSync();
1958 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1959 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
1960
1961 // Up
1962 mDevice->sendUp();
1963 mDevice->sendSync();
1964 ASSERT_NO_FATAL_FAILURE(
1965 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
1966}
1967
Arpit Singh440bf652023-08-09 09:23:43 +00001968TEST_P(TouchIntegrationTest, NotifiesPolicyWhenStylusGestureStarted) {
Prabir Pradhanda20b172022-09-26 17:01:18 +00001969 const Point centerPoint = mDevice->getCenterPoint();
1970
1971 // Send down with the pen tool selected. The policy should be notified of the stylus presence.
1972 mDevice->sendSlot(FIRST_SLOT);
1973 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1974 mDevice->sendToolType(MT_TOOL_PEN);
1975 mDevice->sendDown(centerPoint);
1976 mDevice->sendSync();
1977 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1978 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001979 WithToolType(ToolType::STYLUS))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00001980
1981 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotified(mDeviceInfo.getId()));
1982
1983 // Release the stylus touch.
1984 mDevice->sendUp();
1985 mDevice->sendSync();
1986 ASSERT_NO_FATAL_FAILURE(
1987 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
1988
1989 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotNotified());
1990
1991 // Touch down with the finger, without the pen tool selected. The policy is not notified.
1992 mDevice->sendTrackingId(FIRST_TRACKING_ID);
1993 mDevice->sendToolType(MT_TOOL_FINGER);
1994 mDevice->sendDown(centerPoint);
1995 mDevice->sendSync();
1996 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
1997 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001998 WithToolType(ToolType::FINGER))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00001999
2000 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotNotified());
2001
2002 mDevice->sendUp();
2003 mDevice->sendSync();
2004 ASSERT_NO_FATAL_FAILURE(
2005 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2006
2007 // Send a move event with the stylus tool without BTN_TOUCH to generate a hover enter.
2008 // The policy should be notified of the stylus presence.
2009 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2010 mDevice->sendToolType(MT_TOOL_PEN);
2011 mDevice->sendMove(centerPoint);
2012 mDevice->sendSync();
2013 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2014 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002015 WithToolType(ToolType::STYLUS))));
Prabir Pradhanda20b172022-09-26 17:01:18 +00002016
2017 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotified(mDeviceInfo.getId()));
2018}
2019
Arpit Singh440bf652023-08-09 09:23:43 +00002020TEST_P(TouchIntegrationTest, ExternalStylusConnectedDuringTouchGesture) {
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002021 const Point centerPoint = mDevice->getCenterPoint();
2022
2023 // Down
2024 mDevice->sendSlot(FIRST_SLOT);
2025 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2026 mDevice->sendDown(centerPoint);
2027 mDevice->sendSync();
2028 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2029 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
2030
2031 // Move
2032 mDevice->sendMove(centerPoint + Point(1, 1));
2033 mDevice->sendSync();
2034 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2035 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
2036
2037 // Connecting an external stylus mid-gesture should not interrupt the ongoing gesture stream.
2038 auto externalStylus = createUinputDevice<UinputExternalStylus>();
2039 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002040 const auto stylusInfo = waitForDevice(externalStylus->getName());
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002041 ASSERT_TRUE(stylusInfo);
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002042
2043 // Move
2044 mDevice->sendMove(centerPoint + Point(2, 2));
2045 mDevice->sendSync();
2046 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2047 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
2048
2049 // Disconnecting an external stylus mid-gesture should not interrupt the ongoing gesture stream.
2050 externalStylus.reset();
2051 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Prabir Pradhan85cf63e2023-08-07 21:02:13 +00002052 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2053
2054 // Up
2055 mDevice->sendUp();
2056 mDevice->sendSync();
2057 ASSERT_NO_FATAL_FAILURE(
2058 mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
2059
2060 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2061}
2062
Arpit Singh440bf652023-08-09 09:23:43 +00002063INSTANTIATE_TEST_SUITE_P(TouchIntegrationTestDisplayVariants, TouchIntegrationTest,
2064 testing::Values(TouchIntegrationTestDisplays::DISPLAY_INTERNAL,
2065 TouchIntegrationTestDisplays::DISPLAY_INPUT_PORT,
2066 TouchIntegrationTestDisplays::DISPLAY_UNIQUE_ID));
2067
Prabir Pradhan124ea442022-10-28 20:27:44 +00002068// --- StylusButtonIntegrationTest ---
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002069
Prabir Pradhan124ea442022-10-28 20:27:44 +00002070// Verify the behavior of button presses reported by various kinds of styluses, including buttons
2071// reported by the touchscreen's device, by a fused external stylus, and by an un-fused external
2072// stylus.
2073template <typename UinputStylusDevice>
Arpit Singh440bf652023-08-09 09:23:43 +00002074class StylusButtonIntegrationTest : public BaseTouchIntegrationTest {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002075protected:
2076 void SetUp() override {
2077#if !defined(__ANDROID__)
2078 GTEST_SKIP();
2079#endif
Arpit Singh440bf652023-08-09 09:23:43 +00002080 BaseTouchIntegrationTest::SetUp();
Prabir Pradhan124ea442022-10-28 20:27:44 +00002081 mTouchscreen = mDevice.get();
2082 mTouchscreenInfo = mDeviceInfo;
2083
2084 setUpStylusDevice();
2085 }
2086
2087 UinputStylusDevice* mStylus{nullptr};
2088 InputDeviceInfo mStylusInfo{};
2089
2090 UinputTouchScreen* mTouchscreen{nullptr};
2091 InputDeviceInfo mTouchscreenInfo{};
2092
2093private:
2094 // When we are attempting to test stylus button events that are sent from the touchscreen,
2095 // use the same Uinput device for the touchscreen and the stylus.
2096 template <typename T = UinputStylusDevice>
2097 std::enable_if_t<std::is_same_v<UinputTouchScreen, T>, void> setUpStylusDevice() {
2098 mStylus = mDevice.get();
2099 mStylusInfo = mDeviceInfo;
2100 }
2101
2102 // When we are attempting to stylus buttons from an external stylus being merged with touches
2103 // from a touchscreen, create a new Uinput device through which stylus buttons can be injected.
2104 template <typename T = UinputStylusDevice>
2105 std::enable_if_t<!std::is_same_v<UinputTouchScreen, T>, void> setUpStylusDevice() {
2106 mStylusDeviceLifecycleTracker = createUinputDevice<T>();
2107 mStylus = mStylusDeviceLifecycleTracker.get();
2108 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002109 const auto info = waitForDevice(mStylus->getName());
Prabir Pradhan124ea442022-10-28 20:27:44 +00002110 ASSERT_TRUE(info);
2111 mStylusInfo = *info;
2112 }
2113
2114 std::unique_ptr<UinputStylusDevice> mStylusDeviceLifecycleTracker{};
2115
2116 // Hide the base class's device to expose it with a different name for readability.
Arpit Singh440bf652023-08-09 09:23:43 +00002117 using BaseTouchIntegrationTest::mDevice;
2118 using BaseTouchIntegrationTest::mDeviceInfo;
Prabir Pradhan124ea442022-10-28 20:27:44 +00002119};
2120
2121using StylusButtonIntegrationTestTypes =
2122 ::testing::Types<UinputTouchScreen, UinputExternalStylus, UinputExternalStylusWithPressure>;
2123TYPED_TEST_SUITE(StylusButtonIntegrationTest, StylusButtonIntegrationTestTypes);
2124
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002125TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsGenerateKeyEvents) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002126 const auto stylusId = TestFixture::mStylusInfo.getId();
2127
2128 TestFixture::mStylus->pressKey(BTN_STYLUS);
2129 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2130 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2131 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2132
2133 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2134 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002135 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002136 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhane1a41a82022-10-14 18:06:50 +00002137}
2138
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002139TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingTouchGesture) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002140 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2141 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2142 const auto stylusId = TestFixture::mStylusInfo.getId();
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002143
2144 // Press the stylus button.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002145 TestFixture::mStylus->pressKey(BTN_STYLUS);
2146 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002147 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002148 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002149
2150 // Start and finish a stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002151 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2152 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2153 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2154 TestFixture::mTouchscreen->sendDown(centerPoint);
2155 TestFixture::mTouchscreen->sendSync();
2156 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002157 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002158 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002159 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2160 WithDeviceId(touchscreenId))));
2161 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002162 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002163 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002164 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2165 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002166
Prabir Pradhan124ea442022-10-28 20:27:44 +00002167 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2168 TestFixture::mTouchscreen->sendSync();
2169 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002170 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002171 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002172 WithDeviceId(touchscreenId))));
2173 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002174 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002175 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002176 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002177
2178 // Release the stylus button.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002179 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2180 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002181 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002182 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002183}
2184
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002185TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingHoveringTouchGesture) {
Prabir Pradhan9a561c22022-11-07 16:11:23 +00002186 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2187 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2188 const auto stylusId = TestFixture::mStylusInfo.getId();
2189 auto toolTypeDevice =
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002190 AllOf(WithToolType(ToolType::STYLUS), WithDeviceId(touchscreenId));
Prabir Pradhan9a561c22022-11-07 16:11:23 +00002191
2192 // Press the stylus button.
2193 TestFixture::mStylus->pressKey(BTN_STYLUS);
2194 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2195 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2196 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2197
2198 // Start hovering with the stylus.
2199 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2200 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2201 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2202 TestFixture::mTouchscreen->sendMove(centerPoint);
2203 TestFixture::mTouchscreen->sendSync();
2204 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2205 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2206 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2207 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2208 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2209 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2210 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2211 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
2212 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2213
2214 // Touch down with the stylus.
2215 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2216 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2217 TestFixture::mTouchscreen->sendDown(centerPoint);
2218 TestFixture::mTouchscreen->sendSync();
2219 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2220 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
2221 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2222
2223 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2224 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
2225 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2226
2227 // Stop touching with the stylus, and start hovering.
2228 TestFixture::mTouchscreen->sendUp();
2229 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2230 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2231 TestFixture::mTouchscreen->sendMove(centerPoint);
2232 TestFixture::mTouchscreen->sendSync();
2233 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2234 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_UP),
2235 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2236 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2237 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2238 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2239 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2240 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2241 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2242
2243 // Stop hovering.
2244 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2245 TestFixture::mTouchscreen->sendSync();
2246 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2247 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
2248 WithButtonState(0))));
2249 // TODO(b/257971675): Fix inconsistent button state when exiting hover.
2250 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2251 AllOf(toolTypeDevice, WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
2252 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
2253
2254 // Release the stylus button.
2255 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2256 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2257 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
2258 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2259}
2260
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002261TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsWithinTouchGesture) {
Prabir Pradhan124ea442022-10-28 20:27:44 +00002262 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2263 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2264 const auto stylusId = TestFixture::mStylusInfo.getId();
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002265
2266 // Start a stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002267 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2268 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2269 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2270 TestFixture::mTouchscreen->sendDown(centerPoint);
2271 TestFixture::mTouchscreen->sendSync();
2272 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002273 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002274 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002275 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002276
2277 // Press and release a stylus button. Each change in button state also generates a MOVE event.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002278 TestFixture::mStylus->pressKey(BTN_STYLUS);
2279 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002280 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002281 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2282 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002283 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002284 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002285 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2286 WithDeviceId(touchscreenId))));
2287 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002288 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002289 WithToolType(ToolType::STYLUS),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002290 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY),
2291 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002292
Prabir Pradhan124ea442022-10-28 20:27:44 +00002293 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2294 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002295 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002296 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2297 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002298 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002299 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002300 WithDeviceId(touchscreenId))));
2301 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002302 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002303 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002304 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002305
2306 // Finish the stylus gesture.
Prabir Pradhan124ea442022-10-28 20:27:44 +00002307 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2308 TestFixture::mTouchscreen->sendSync();
2309 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002310 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002311 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan124ea442022-10-28 20:27:44 +00002312 WithDeviceId(touchscreenId))));
Prabir Pradhan7bffbf52022-10-14 20:31:53 +00002313}
2314
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002315TYPED_TEST(StylusButtonIntegrationTest, StylusButtonMotionEventsDisabled) {
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002316 TestFixture::mFakePolicy->setStylusButtonMotionEventsEnabled(false);
2317 TestFixture::mReader->requestRefreshConfiguration(
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002318 InputReaderConfiguration::Change::STYLUS_BUTTON_REPORTING);
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002319
2320 const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
2321 const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
2322 const auto stylusId = TestFixture::mStylusInfo.getId();
2323
2324 // Start a stylus gesture. By the time this event is processed, the configuration change that
2325 // was requested is guaranteed to be completed.
2326 TestFixture::mTouchscreen->sendSlot(FIRST_SLOT);
2327 TestFixture::mTouchscreen->sendTrackingId(FIRST_TRACKING_ID);
2328 TestFixture::mTouchscreen->sendToolType(MT_TOOL_PEN);
2329 TestFixture::mTouchscreen->sendDown(centerPoint);
2330 TestFixture::mTouchscreen->sendSync();
2331 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2332 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002333 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002334 WithDeviceId(touchscreenId))));
2335
2336 // Press and release a stylus button. Each change only generates a MOVE motion event.
2337 // Key events are unaffected.
2338 TestFixture::mStylus->pressKey(BTN_STYLUS);
2339 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2340 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_KEYBOARD),
2341 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2342 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2343 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002344 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002345 WithDeviceId(touchscreenId))));
2346
2347 TestFixture::mStylus->releaseKey(BTN_STYLUS);
2348 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyKeyWasCalled(
2349 AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_KEYBOARD),
2350 WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
2351 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2352 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002353 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002354 WithDeviceId(touchscreenId))));
2355
2356 // Finish the stylus gesture.
2357 TestFixture::mTouchscreen->sendTrackingId(INVALID_TRACKING_ID);
2358 TestFixture::mTouchscreen->sendSync();
2359 ASSERT_NO_FATAL_FAILURE(TestFixture::mTestListener->assertNotifyMotionWasCalled(
2360 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002361 WithToolType(ToolType::STYLUS), WithButtonState(0),
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00002362 WithDeviceId(touchscreenId))));
2363}
2364
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002365// --- ExternalStylusIntegrationTest ---
2366
2367// Verify the behavior of an external stylus. An external stylus can report pressure or button
2368// data independently of the touchscreen, which is then sent as a MotionEvent as part of an
2369// ongoing stylus gesture that is being emitted by the touchscreen.
Arpit Singh440bf652023-08-09 09:23:43 +00002370using ExternalStylusIntegrationTest = BaseTouchIntegrationTest;
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002371
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002372TEST_F(ExternalStylusIntegrationTest, ExternalStylusConnectionChangesTouchscreenSource) {
2373 // Create an external stylus capable of reporting pressure data that
2374 // should be fused with a touch pointer.
2375 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2376 createUinputDevice<UinputExternalStylusWithPressure>();
2377 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002378 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002379 ASSERT_TRUE(stylusInfo);
2380
2381 // Connecting an external stylus changes the source of the touchscreen.
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002382 const auto deviceInfo = waitForDevice(mDevice->getName());
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002383 ASSERT_TRUE(deviceInfo);
2384 ASSERT_TRUE(isFromSource(deviceInfo->getSources(), STYLUS_FUSION_SOURCE));
2385}
2386
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002387TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureReported) {
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002388 const Point centerPoint = mDevice->getCenterPoint();
2389
2390 // Create an external stylus capable of reporting pressure data that
2391 // should be fused with a touch pointer.
2392 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2393 createUinputDevice<UinputExternalStylusWithPressure>();
2394 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002395 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002396 ASSERT_TRUE(stylusInfo);
2397
2398 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2399
2400 const auto touchscreenId = mDeviceInfo.getId();
2401
2402 // Set a pressure value on the stylus. It doesn't generate any events.
2403 const auto& RAW_PRESSURE_MAX = UinputExternalStylusWithPressure::RAW_PRESSURE_MAX;
2404 stylus->setPressure(100);
2405 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2406
2407 // Start a finger gesture, and ensure it shows up as stylus gesture
2408 // with the pressure set by the external stylus.
Dominik Laskowski2f01d772022-03-23 16:01:29 -07002409 mDevice->sendSlot(FIRST_SLOT);
Chris Ye1b0c7342020-07-28 21:57:03 -07002410 mDevice->sendTrackingId(FIRST_TRACKING_ID);
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002411 mDevice->sendToolType(MT_TOOL_FINGER);
Prabir Pradhanb54ffb22022-10-27 18:03:34 +00002412 mDevice->sendDown(centerPoint);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002413 mDevice->sendSync();
2414 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002415 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithToolType(ToolType::STYLUS),
2416 WithButtonState(0), WithSource(STYLUS_FUSION_SOURCE), WithDeviceId(touchscreenId),
2417 WithPressure(100.f / RAW_PRESSURE_MAX))));
Dominik Laskowski2f01d772022-03-23 16:01:29 -07002418
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002419 // Change the pressure on the external stylus, and ensure the touchscreen generates a MOVE
2420 // event with the updated pressure.
2421 stylus->setPressure(200);
Vaibhav Devmuraridd82b8e2022-08-16 15:34:01 +00002422 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002423 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithToolType(ToolType::STYLUS),
2424 WithButtonState(0), WithSource(STYLUS_FUSION_SOURCE), WithDeviceId(touchscreenId),
2425 WithPressure(200.f / RAW_PRESSURE_MAX))));
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002426
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002427 // The external stylus did not generate any events.
2428 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2429 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
2430}
2431
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002432TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureNotReported) {
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002433 const Point centerPoint = mDevice->getCenterPoint();
2434
2435 // Create an external stylus capable of reporting pressure data that
2436 // should be fused with a touch pointer.
2437 std::unique_ptr<UinputExternalStylusWithPressure> stylus =
2438 createUinputDevice<UinputExternalStylusWithPressure>();
2439 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002440 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002441 ASSERT_TRUE(stylusInfo);
2442
2443 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2444
2445 const auto touchscreenId = mDeviceInfo.getId();
2446
2447 // Set a pressure value of 0 on the stylus. It doesn't generate any events.
2448 const auto& RAW_PRESSURE_MAX = UinputExternalStylusWithPressure::RAW_PRESSURE_MAX;
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002449 // Send a non-zero value first to prevent the kernel from consuming the zero event.
2450 stylus->setPressure(100);
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002451 stylus->setPressure(0);
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002452 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002453
2454 // Start a finger gesture. The touch device will withhold generating any touches for
2455 // up to 72 milliseconds while waiting for pressure data from the external stylus.
2456 mDevice->sendSlot(FIRST_SLOT);
2457 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2458 mDevice->sendToolType(MT_TOOL_FINGER);
2459 mDevice->sendDown(centerPoint);
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002460 const auto syncTime = std::chrono::system_clock::now();
2461 // After 72 ms, the event *will* be generated. If we wait the full 72 ms to check that NO event
2462 // is generated in that period, there will be a race condition between the event being generated
2463 // and the test's wait timeout expiring. Thus, we wait for a shorter duration in the test, which
2464 // will reduce the liklihood of the race condition occurring.
2465 const auto waitUntilTimeForNoEvent =
2466 syncTime + std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT / 2));
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07002467 mDevice->sendSync();
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002468 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled(waitUntilTimeForNoEvent));
Michael Wrightd02c5b62014-02-10 15:10:22 -08002469
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002470 // Since the external stylus did not report a pressure value within the timeout,
2471 // it shows up as a finger pointer.
Prabir Pradhanafb7d612024-01-08 22:45:24 +00002472 const auto waitUntilTimeForEvent = syncTime +
2473 std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT)) + EVENT_HAPPENED_TIMEOUT;
2474 ASSERT_NO_FATAL_FAILURE(
2475 mTestListener->assertNotifyMotionWasCalled(AllOf(WithMotionAction(
2476 AMOTION_EVENT_ACTION_DOWN),
2477 WithSource(AINPUT_SOURCE_TOUCHSCREEN |
2478 AINPUT_SOURCE_STYLUS),
2479 WithToolType(ToolType::FINGER),
2480 WithDeviceId(touchscreenId),
2481 WithPressure(1.f)),
2482 waitUntilTimeForEvent));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002483
2484 // Change the pressure on the external stylus. Since the pressure was not present at the start
2485 // of the gesture, it is ignored for now.
2486 stylus->setPressure(200);
2487 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2488
2489 // Finish the finger gesture.
Michael Wrightd02c5b62014-02-10 15:10:22 -08002490 mDevice->sendTrackingId(INVALID_TRACKING_ID);
2491 mDevice->sendSync();
2492 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
2493 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002494 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002495 WithToolType(ToolType::FINGER))));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002496
2497 // Start a new gesture. Since we have a valid pressure value, it shows up as a stylus.
2498 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2499 mDevice->sendToolType(MT_TOOL_FINGER);
2500 mDevice->sendDown(centerPoint);
2501 mDevice->sendSync();
2502 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002503 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithSource(STYLUS_FUSION_SOURCE),
2504 WithToolType(ToolType::STYLUS), WithButtonState(0), WithDeviceId(touchscreenId),
2505 WithPressure(200.f / RAW_PRESSURE_MAX))));
Prabir Pradhan484d55a2022-10-14 23:17:16 +00002506
2507 // The external stylus did not generate any events.
2508 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2509 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002510}
Siarhei Vishniakou1983a712021-06-04 19:27:09 +00002511
Prabir Pradhan39d60aa2023-07-13 22:01:04 +00002512TEST_F(ExternalStylusIntegrationTest, UnfusedExternalStylus) {
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002513 const Point centerPoint = mDevice->getCenterPoint();
2514
2515 // Create an external stylus device that does not support pressure. It should not affect any
2516 // touch pointers.
2517 std::unique_ptr<UinputExternalStylus> stylus = createUinputDevice<UinputExternalStylus>();
2518 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
Siarhei Vishniakoud790d6b2024-02-21 10:34:59 -08002519 const auto stylusInfo = waitForDevice(stylus->getName());
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002520 ASSERT_TRUE(stylusInfo);
2521
2522 ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
2523
2524 const auto touchscreenId = mDeviceInfo.getId();
2525
2526 // Start a finger gesture and ensure a finger pointer is generated for it, without waiting for
2527 // pressure data from the external stylus.
2528 mDevice->sendSlot(FIRST_SLOT);
2529 mDevice->sendTrackingId(FIRST_TRACKING_ID);
2530 mDevice->sendToolType(MT_TOOL_FINGER);
2531 mDevice->sendDown(centerPoint);
2532 auto waitUntil = std::chrono::system_clock::now() +
2533 std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT));
2534 mDevice->sendSync();
2535 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00002536 mTestListener->assertNotifyMotionWasCalled(AllOf(WithMotionAction(
2537 AMOTION_EVENT_ACTION_DOWN),
2538 WithToolType(ToolType::FINGER),
2539 WithSource(AINPUT_SOURCE_TOUCHSCREEN |
2540 AINPUT_SOURCE_STYLUS),
2541 WithButtonState(0),
2542 WithDeviceId(touchscreenId),
2543 WithPressure(1.f)),
2544 waitUntil));
Prabir Pradhan3f7545f2022-10-19 16:56:39 +00002545
2546 // The external stylus did not generate any events.
2547 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
2548 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
2549}
2550
Michael Wrightd02c5b62014-02-10 15:10:22 -08002551// --- InputDeviceTest ---
2552class InputDeviceTest : public testing::Test {
2553protected:
2554 static const char* DEVICE_NAME;
2555 static const char* DEVICE_LOCATION;
2556 static const int32_t DEVICE_ID;
2557 static const int32_t DEVICE_GENERATION;
2558 static const int32_t DEVICE_CONTROLLER_NUMBER;
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002559 static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002560 static const int32_t EVENTHUB_ID;
2561 static const std::string DEVICE_BLUETOOTH_ADDRESS;
2562
2563 std::shared_ptr<FakeEventHub> mFakeEventHub;
2564 sp<FakeInputReaderPolicy> mFakePolicy;
2565 std::unique_ptr<TestInputListener> mFakeListener;
2566 std::unique_ptr<InstrumentedInputReader> mReader;
2567 std::shared_ptr<InputDevice> mDevice;
2568
2569 void SetUp() override {
2570 mFakeEventHub = std::make_unique<FakeEventHub>();
2571 mFakePolicy = sp<FakeInputReaderPolicy>::make();
2572 mFakeListener = std::make_unique<TestInputListener>();
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002573 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Michael Wrightd02c5b62014-02-10 15:10:22 -08002574 *mFakeListener);
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002575 InputDeviceIdentifier identifier;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002576 identifier.name = DEVICE_NAME;
2577 identifier.location = DEVICE_LOCATION;
2578 identifier.bluetoothAddress = DEVICE_BLUETOOTH_ADDRESS;
2579 mDevice = std::make_shared<InputDevice>(mReader->getContext(), DEVICE_ID, DEVICE_GENERATION,
2580 identifier);
2581 mReader->pushNextDevice(mDevice);
2582 mFakeEventHub->addDevice(EVENTHUB_ID, DEVICE_NAME, ftl::Flags<InputDeviceClass>(0));
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002583 mReader->loopOnce();
Michael Wrightd02c5b62014-02-10 15:10:22 -08002584 }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002585
2586 void TearDown() override {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002587 mFakeListener.reset();
2588 mFakePolicy.clear();
2589 }
2590};
2591
2592const char* InputDeviceTest::DEVICE_NAME = "device";
2593const char* InputDeviceTest::DEVICE_LOCATION = "USB1";
2594const int32_t InputDeviceTest::DEVICE_ID = END_RESERVED_ID + 1000;
2595const int32_t InputDeviceTest::DEVICE_GENERATION = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002596const int32_t InputDeviceTest::DEVICE_CONTROLLER_NUMBER = 0;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002597const ftl::Flags<InputDeviceClass> InputDeviceTest::DEVICE_CLASSES =
2598 InputDeviceClass::KEYBOARD | InputDeviceClass::TOUCH | InputDeviceClass::JOYSTICK;
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002599const int32_t InputDeviceTest::EVENTHUB_ID = 1;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002600const std::string InputDeviceTest::DEVICE_BLUETOOTH_ADDRESS = "11:AA:22:BB:33:CC";
2601
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002602TEST_F(InputDeviceTest, ImmutableProperties) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002603 ASSERT_EQ(DEVICE_ID, mDevice->getId());
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002604 ASSERT_STREQ(DEVICE_NAME, mDevice->getName().c_str());
2605 ASSERT_EQ(ftl::Flags<InputDeviceClass>(0), mDevice->getClasses());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002606}
Siarhei Vishniakou4f94c1a2022-07-13 07:29:51 -07002607
Michael Wrightd02c5b62014-02-10 15:10:22 -08002608TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsFalse) {
2609 ASSERT_EQ(mDevice->isEnabled(), false);
2610}
2611
2612TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
2613 // Configuration.
2614 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002615 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002616
2617 // Reset.
2618 unused += mDevice->reset(ARBITRARY_TIME);
2619
2620 NotifyDeviceResetArgs resetArgs;
2621 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
2622 ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
2623 ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
2624
2625 // Metadata.
2626 ASSERT_TRUE(mDevice->isIgnored());
2627 ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mDevice->getSources());
2628
2629 InputDeviceInfo info = mDevice->getDeviceInfo();
2630 ASSERT_EQ(DEVICE_ID, info.getId());
2631 ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.c_str());
2632 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NONE, info.getKeyboardType());
2633 ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, info.getSources());
2634
2635 // State queries.
2636 ASSERT_EQ(0, mDevice->getMetaState());
2637
2638 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, 0))
2639 << "Ignored device should return unknown key code state.";
2640 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 0))
2641 << "Ignored device should return unknown scan code state.";
2642 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 0))
2643 << "Ignored device should return unknown switch state.";
2644
2645 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B};
2646 uint8_t flags[2] = { 0, 1 };
2647 ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, keyCodes, flags))
2648 << "Ignored device should never mark any key codes.";
2649 ASSERT_EQ(0, flags[0]) << "Flag for unsupported key should be unchanged.";
2650 ASSERT_EQ(1, flags[1]) << "Flag for unsupported key should be unchanged.";
2651}
2652
2653TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRequestsToMappers) {
2654 // Configuration.
2655 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "key", "value");
2656
2657 FakeInputMapper& mapper1 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00002658 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2659 AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002660 mapper1.setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC);
2661 mapper1.setMetaState(AMETA_ALT_ON);
2662 mapper1.addSupportedKeyCode(AKEYCODE_A);
2663 mapper1.addSupportedKeyCode(AKEYCODE_B);
2664 mapper1.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
2665 mapper1.setKeyCodeState(AKEYCODE_B, AKEY_STATE_UP);
2666 mapper1.setScanCodeState(2, AKEY_STATE_DOWN);
2667 mapper1.setScanCodeState(3, AKEY_STATE_UP);
2668 mapper1.setSwitchState(4, AKEY_STATE_DOWN);
2669
2670 FakeInputMapper& mapper2 =
Arpit Singh8e6fb252023-04-06 11:49:17 +00002671 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2672 AINPUT_SOURCE_TOUCHSCREEN);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002673 mapper2.setMetaState(AMETA_SHIFT_ON);
2674
2675 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002676 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002677
Harry Cuttsf13161a2023-03-08 14:15:49 +00002678 std::optional<std::string> propertyValue = mDevice->getConfiguration().getString("key");
2679 ASSERT_TRUE(propertyValue.has_value())
Michael Wrightd02c5b62014-02-10 15:10:22 -08002680 << "Device should have read configuration during configuration phase.";
Harry Cuttsf13161a2023-03-08 14:15:49 +00002681 ASSERT_EQ("value", *propertyValue);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002682
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002683 ASSERT_NO_FATAL_FAILURE(mapper1.assertConfigureWasCalled());
2684 ASSERT_NO_FATAL_FAILURE(mapper2.assertConfigureWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002685
2686 // Reset
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002687 unused += mDevice->reset(ARBITRARY_TIME);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002688 ASSERT_NO_FATAL_FAILURE(mapper1.assertResetWasCalled());
2689 ASSERT_NO_FATAL_FAILURE(mapper2.assertResetWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002690
2691 NotifyDeviceResetArgs resetArgs;
2692 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
2693 ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
2694 ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
2695
2696 // Metadata.
2697 ASSERT_FALSE(mDevice->isIgnored());
2698 ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), mDevice->getSources());
2699
Siarhei Vishniakou1983a712021-06-04 19:27:09 +00002700 InputDeviceInfo info = mDevice->getDeviceInfo();
Michael Wrightd02c5b62014-02-10 15:10:22 -08002701 ASSERT_EQ(DEVICE_ID, info.getId());
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002702 ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002703 ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, info.getKeyboardType());
2704 ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), info.getSources());
2705
2706 // State queries.
2707 ASSERT_EQ(AMETA_ALT_ON | AMETA_SHIFT_ON, mDevice->getMetaState())
2708 << "Should query mappers and combine meta states.";
2709
2710 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2711 << "Should return unknown key code state when source not supported.";
2712 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2713 << "Should return unknown scan code state when source not supported.";
2714 ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
2715 << "Should return unknown switch state when source not supported.";
2716
2717 ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, AKEYCODE_A))
2718 << "Should query mapper when source is supported.";
2719 ASSERT_EQ(AKEY_STATE_UP, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 3))
2720 << "Should query mapper when source is supported.";
2721 ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 4))
2722 << "Should query mapper when source is supported.";
2723
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002724 const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2};
Michael Wrightd02c5b62014-02-10 15:10:22 -08002725 uint8_t flags[4] = { 0, 0, 0, 1 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002726 ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -08002727 << "Should do nothing when source is unsupported.";
2728 ASSERT_EQ(0, flags[0]) << "Flag should be unchanged when source is unsupported.";
2729 ASSERT_EQ(0, flags[1]) << "Flag should be unchanged when source is unsupported.";
2730 ASSERT_EQ(0, flags[2]) << "Flag should be unchanged when source is unsupported.";
2731 ASSERT_EQ(1, flags[3]) << "Flag should be unchanged when source is unsupported.";
2732
Siarhei Vishniakou74007942022-06-13 13:57:47 -07002733 ASSERT_TRUE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, keyCodes, flags))
Michael Wrightd02c5b62014-02-10 15:10:22 -08002734 << "Should query mapper when source is supported.";
2735 ASSERT_EQ(1, flags[0]) << "Flag for supported key should be set.";
2736 ASSERT_EQ(1, flags[1]) << "Flag for supported key should be set.";
2737 ASSERT_EQ(0, flags[2]) << "Flag for unsupported key should be unchanged.";
2738 ASSERT_EQ(1, flags[3]) << "Flag for unsupported key should be unchanged.";
2739
2740 // Event handling.
2741 RawEvent event;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08002742 event.deviceId = EVENTHUB_ID;
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002743 unused += mDevice->process(&event, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002744
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08002745 ASSERT_NO_FATAL_FAILURE(mapper1.assertProcessWasCalled());
2746 ASSERT_NO_FATAL_FAILURE(mapper2.assertProcessWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002747}
2748
Yeabkal Wubshitb1b96db2024-01-24 12:47:00 -08002749TEST_F(InputDeviceTest, Configure_SmoothScrollViewBehaviorNotSet) {
2750 // Set some behavior to force the configuration to be update.
2751 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "1");
2752 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2753 AINPUT_SOURCE_KEYBOARD);
2754
2755 std::list<NotifyArgs> unused =
2756 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2757 /*changes=*/{});
2758
2759 ASSERT_FALSE(mDevice->getDeviceInfo().getViewBehavior().shouldSmoothScroll.has_value());
2760}
2761
2762TEST_F(InputDeviceTest, Configure_SmoothScrollViewBehaviorEnabled) {
2763 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.viewBehavior_smoothScroll", "1");
2764 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2765 AINPUT_SOURCE_KEYBOARD);
2766
2767 std::list<NotifyArgs> unused =
2768 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2769 /*changes=*/{});
2770
2771 ASSERT_TRUE(mDevice->getDeviceInfo().getViewBehavior().shouldSmoothScroll.value_or(false));
2772}
2773
Yeabkal Wubshite03e8b12023-06-27 16:23:12 -07002774TEST_F(InputDeviceTest, WakeDevice_AddsWakeFlagToProcessNotifyArgs) {
2775 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "1");
2776 FakeInputMapper& mapper =
2777 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2778 AINPUT_SOURCE_KEYBOARD);
2779 NotifyMotionArgs args1;
2780 NotifySwitchArgs args2;
2781 NotifyKeyArgs args3;
2782 mapper.setProcessResult({args1, args2, args3});
2783
2784 InputReaderConfiguration config;
2785 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2786
2787 RawEvent event;
2788 event.deviceId = EVENTHUB_ID;
2789 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2790
2791 for (auto& arg : notifyArgs) {
2792 if (const auto notifyMotionArgs = std::get_if<NotifyMotionArgs>(&arg)) {
2793 ASSERT_EQ(POLICY_FLAG_WAKE, notifyMotionArgs->policyFlags);
2794 } else if (const auto notifySwitchArgs = std::get_if<NotifySwitchArgs>(&arg)) {
2795 ASSERT_EQ(POLICY_FLAG_WAKE, notifySwitchArgs->policyFlags);
2796 } else if (const auto notifyKeyArgs = std::get_if<NotifyKeyArgs>(&arg)) {
2797 ASSERT_EQ(POLICY_FLAG_WAKE, notifyKeyArgs->policyFlags);
2798 }
2799 }
2800}
2801
2802TEST_F(InputDeviceTest, NotWakeDevice_DoesNotAddWakeFlagToProcessNotifyArgs) {
2803 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "0");
2804 FakeInputMapper& mapper =
2805 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2806 AINPUT_SOURCE_KEYBOARD);
2807 NotifyMotionArgs args;
2808 mapper.setProcessResult({args});
2809
2810 InputReaderConfiguration config;
2811 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2812
2813 RawEvent event;
2814 event.deviceId = EVENTHUB_ID;
2815 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2816
2817 // POLICY_FLAG_WAKE is not added to the NotifyArgs.
2818 ASSERT_EQ(0u, std::get<NotifyMotionArgs>(notifyArgs.front()).policyFlags);
2819}
2820
2821TEST_F(InputDeviceTest, NotWakeDevice_DoesNotRemoveExistingWakeFlagFromProcessNotifyArgs) {
2822 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "0");
2823 FakeInputMapper& mapper =
2824 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2825 AINPUT_SOURCE_KEYBOARD);
2826 NotifyMotionArgs args;
2827 args.policyFlags = POLICY_FLAG_WAKE;
2828 mapper.setProcessResult({args});
2829
2830 InputReaderConfiguration config;
2831 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
2832
2833 RawEvent event;
2834 event.deviceId = EVENTHUB_ID;
2835 std::list<NotifyArgs> notifyArgs = mDevice->process(&event, 1);
2836
2837 // The POLICY_FLAG_WAKE is preserved, despite the device being a non-wake device.
2838 ASSERT_EQ(POLICY_FLAG_WAKE, std::get<NotifyMotionArgs>(notifyArgs.front()).policyFlags);
2839}
2840
Arthur Hung2c9a3342019-07-23 14:18:59 +08002841// A single input device is associated with a specific display. Check that:
2842// 1. Device is disabled if the viewport corresponding to the associated display is not found
Arpit Singh48189772023-05-30 14:12:49 +00002843// 2. Device is disabled when configure API is called
Arthur Hung2c9a3342019-07-23 14:18:59 +08002844TEST_F(InputDeviceTest, Configure_AssignsDisplayPort) {
Arpit Singh8e6fb252023-04-06 11:49:17 +00002845 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2846 AINPUT_SOURCE_TOUCHSCREEN);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002847
2848 // First Configuration.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002849 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002850 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2851 /*changes=*/{});
Arthur Hung2c9a3342019-07-23 14:18:59 +08002852
2853 // Device should be enabled by default.
2854 ASSERT_TRUE(mDevice->isEnabled());
2855
2856 // Prepare associated info.
2857 constexpr uint8_t hdmi = 1;
2858 const std::string UNIQUE_ID = "local:1";
2859
2860 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002861 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002862 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002863 // Device should be disabled because it is associated with a specific display via
2864 // input port <-> display port association, but the corresponding display is not found
2865 ASSERT_FALSE(mDevice->isEnabled());
2866
2867 // Prepare displays.
2868 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Harry Cutts33476232023-01-30 19:57:29 +00002869 ui::ROTATION_0, /*isActive=*/true, UNIQUE_ID, hdmi,
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00002870 ViewportType::INTERNAL);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002871 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002872 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002873 ASSERT_TRUE(mDevice->isEnabled());
2874
2875 // Device should be disabled after set disable.
2876 mFakePolicy->addDisabledDevice(mDevice->getId());
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002877 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002878 InputReaderConfiguration::Change::ENABLED_STATE);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002879 ASSERT_FALSE(mDevice->isEnabled());
2880
2881 // Device should still be disabled even found the associated display.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002882 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002883 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08002884 ASSERT_FALSE(mDevice->isEnabled());
2885}
Michael Wrightd02c5b62014-02-10 15:10:22 -08002886
Christine Franks1ba71cc2021-04-07 14:37:42 -07002887TEST_F(InputDeviceTest, Configure_AssignsDisplayUniqueId) {
2888 // Device should be enabled by default.
2889 mFakePolicy->clearViewports();
Arpit Singh8e6fb252023-04-06 11:49:17 +00002890 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2891 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002892 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002893 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2894 /*changes=*/{});
Christine Franks1ba71cc2021-04-07 14:37:42 -07002895 ASSERT_TRUE(mDevice->isEnabled());
2896
2897 // Device should be disabled because it is associated with a specific display, but the
2898 // corresponding display is not found.
Christine Franks2a2293c2022-01-18 11:51:16 -08002899 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002900 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002901 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002902 ASSERT_FALSE(mDevice->isEnabled());
2903
2904 // Device should be enabled when a display is found.
2905 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00002906 ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
Christine Franks1ba71cc2021-04-07 14:37:42 -07002907 NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002908 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002909 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002910 ASSERT_TRUE(mDevice->isEnabled());
2911
2912 // Device should be disabled after set disable.
2913 mFakePolicy->addDisabledDevice(mDevice->getId());
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002914 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002915 InputReaderConfiguration::Change::ENABLED_STATE);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002916 ASSERT_FALSE(mDevice->isEnabled());
2917
2918 // Device should still be disabled even found the associated display.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002919 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002920 InputReaderConfiguration::Change::DISPLAY_INFO);
Christine Franks1ba71cc2021-04-07 14:37:42 -07002921 ASSERT_FALSE(mDevice->isEnabled());
2922}
2923
Christine Franks2a2293c2022-01-18 11:51:16 -08002924TEST_F(InputDeviceTest, Configure_UniqueId_CorrectlyMatches) {
2925 mFakePolicy->clearViewports();
Arpit Singh8e6fb252023-04-06 11:49:17 +00002926 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2927 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002928 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002929 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2930 /*changes=*/{});
Christine Franks2a2293c2022-01-18 11:51:16 -08002931
Christine Franks2a2293c2022-01-18 11:51:16 -08002932 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
2933 mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00002934 ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
Christine Franks2a2293c2022-01-18 11:51:16 -08002935 NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan55c5ee22024-02-14 06:03:02 +00002936 const auto initialGeneration = mDevice->getGeneration();
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07002937 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00002938 InputReaderConfiguration::Change::DISPLAY_INFO);
Antonio Kantek0ac5e092024-04-22 17:10:27 +00002939 ASSERT_EQ(DISPLAY_UNIQUE_ID, mDevice->getAssociatedDisplayUniqueIdByPort());
Prabir Pradhan55c5ee22024-02-14 06:03:02 +00002940 ASSERT_GT(mDevice->getGeneration(), initialGeneration);
2941 ASSERT_EQ(mDevice->getDeviceInfo().getAssociatedDisplayId(), SECONDARY_DISPLAY_ID);
Christine Franks2a2293c2022-01-18 11:51:16 -08002942}
2943
Siarhei Vishniakou30feb8c2022-09-28 10:48:29 -07002944/**
2945 * This test reproduces a crash caused by a dangling reference that remains after device is added
2946 * and removed. The reference is accessed in InputDevice::dump(..);
2947 */
2948TEST_F(InputDeviceTest, DumpDoesNotCrash) {
2949 constexpr int32_t TEST_EVENTHUB_ID = 10;
2950 mFakeEventHub->addDevice(TEST_EVENTHUB_ID, "Test EventHub device", InputDeviceClass::BATTERY);
2951
Harry Cutts33476232023-01-30 19:57:29 +00002952 InputDevice device(mReader->getContext(), /*id=*/1, /*generation=*/2, /*identifier=*/{});
Arpit Singh82f29a12023-06-13 15:05:53 +00002953 auto _ = device.addEventHubDevice(ARBITRARY_TIME, TEST_EVENTHUB_ID,
2954 mFakePolicy->getReaderConfiguration());
Siarhei Vishniakou30feb8c2022-09-28 10:48:29 -07002955 device.removeEventHubDevice(TEST_EVENTHUB_ID);
2956 std::string dumpStr, eventHubDevStr;
2957 device.dump(dumpStr, eventHubDevStr);
2958}
2959
Prabir Pradhanb54ffb22022-10-27 18:03:34 +00002960TEST_F(InputDeviceTest, GetBluetoothAddress) {
2961 const auto& address = mReader->getBluetoothAddress(DEVICE_ID);
2962 ASSERT_TRUE(address);
2963 ASSERT_EQ(DEVICE_BLUETOOTH_ADDRESS, *address);
2964}
2965
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002966TEST_F(InputDeviceTest, KernelBufferOverflowResetsMappers) {
2967 mFakePolicy->clearViewports();
2968 FakeInputMapper& mapper =
2969 mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
2970 AINPUT_SOURCE_KEYBOARD);
2971 std::list<NotifyArgs> unused =
2972 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
2973 /*changes=*/{});
2974
2975 mapper.assertConfigureWasCalled();
2976 mapper.assertResetWasNotCalled();
2977
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -08002978 RawEvent event{.when = ARBITRARY_TIME,
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002979 .readTime = ARBITRARY_TIME,
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -08002980 .deviceId = EVENTHUB_ID,
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002981 .type = EV_SYN,
2982 .code = SYN_REPORT,
2983 .value = 0};
2984
2985 // Events are processed normally.
2986 unused = mDevice->process(&event, /*count=*/1);
2987 mapper.assertProcessWasCalled();
2988
2989 // Simulate a kernel buffer overflow, which generates a SYN_DROPPED event.
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002990 event.type = EV_SYN;
2991 event.code = SYN_DROPPED;
2992 event.value = 0;
2993 unused = mDevice->process(&event, /*count=*/1);
2994 mapper.assertProcessWasNotCalled();
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00002995
2996 // All events until the next SYN_REPORT should be dropped.
2997 event.type = EV_KEY;
2998 event.code = KEY_A;
2999 event.value = 1;
3000 unused = mDevice->process(&event, /*count=*/1);
3001 mapper.assertProcessWasNotCalled();
3002
3003 // We get the SYN_REPORT event now, which is not forwarded to mappers.
Arpit Singh4b4a4572023-11-24 18:19:56 +00003004 // This should reset the mapper.
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003005 event.type = EV_SYN;
3006 event.code = SYN_REPORT;
3007 event.value = 0;
3008 unused = mDevice->process(&event, /*count=*/1);
3009 mapper.assertProcessWasNotCalled();
Arpit Singh4b4a4572023-11-24 18:19:56 +00003010 mapper.assertResetWasCalled();
Prabir Pradhanf8d9e442023-12-06 22:06:13 +00003011
3012 // The mapper receives events normally now.
3013 event.type = EV_KEY;
3014 event.code = KEY_B;
3015 event.value = 1;
3016 unused = mDevice->process(&event, /*count=*/1);
3017 mapper.assertProcessWasCalled();
3018}
3019
Chris Yef59a2f42020-10-16 12:55:26 -07003020// --- SensorInputMapperTest ---
3021
3022class SensorInputMapperTest : public InputMapperTest {
3023protected:
3024 static const int32_t ACCEL_RAW_MIN;
3025 static const int32_t ACCEL_RAW_MAX;
3026 static const int32_t ACCEL_RAW_FUZZ;
3027 static const int32_t ACCEL_RAW_FLAT;
3028 static const int32_t ACCEL_RAW_RESOLUTION;
3029
3030 static const int32_t GYRO_RAW_MIN;
3031 static const int32_t GYRO_RAW_MAX;
3032 static const int32_t GYRO_RAW_FUZZ;
3033 static const int32_t GYRO_RAW_FLAT;
3034 static const int32_t GYRO_RAW_RESOLUTION;
3035
3036 static const float GRAVITY_MS2_UNIT;
3037 static const float DEGREE_RADIAN_UNIT;
3038
3039 void prepareAccelAxes();
3040 void prepareGyroAxes();
3041 void setAccelProperties();
3042 void setGyroProperties();
3043 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::SENSOR); }
3044};
3045
3046const int32_t SensorInputMapperTest::ACCEL_RAW_MIN = -32768;
3047const int32_t SensorInputMapperTest::ACCEL_RAW_MAX = 32768;
3048const int32_t SensorInputMapperTest::ACCEL_RAW_FUZZ = 16;
3049const int32_t SensorInputMapperTest::ACCEL_RAW_FLAT = 0;
3050const int32_t SensorInputMapperTest::ACCEL_RAW_RESOLUTION = 8192;
3051
3052const int32_t SensorInputMapperTest::GYRO_RAW_MIN = -2097152;
3053const int32_t SensorInputMapperTest::GYRO_RAW_MAX = 2097152;
3054const int32_t SensorInputMapperTest::GYRO_RAW_FUZZ = 16;
3055const int32_t SensorInputMapperTest::GYRO_RAW_FLAT = 0;
3056const int32_t SensorInputMapperTest::GYRO_RAW_RESOLUTION = 1024;
3057
3058const float SensorInputMapperTest::GRAVITY_MS2_UNIT = 9.80665f;
3059const float SensorInputMapperTest::DEGREE_RADIAN_UNIT = 0.0174533f;
3060
3061void SensorInputMapperTest::prepareAccelAxes() {
3062 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3063 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3064 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3065 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3066 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Z, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
3067 ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
3068}
3069
3070void SensorInputMapperTest::prepareGyroAxes() {
3071 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RX, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3072 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3073 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RY, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3074 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3075 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RZ, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
3076 GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
3077}
3078
3079void SensorInputMapperTest::setAccelProperties() {
3080 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 0, InputDeviceSensorType::ACCELEROMETER,
3081 /* sensorDataIndex */ 0);
3082 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 1, InputDeviceSensorType::ACCELEROMETER,
3083 /* sensorDataIndex */ 1);
3084 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 2, InputDeviceSensorType::ACCELEROMETER,
3085 /* sensorDataIndex */ 2);
3086 mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP);
3087 addConfigurationProperty("sensor.accelerometer.reportingMode", "0");
3088 addConfigurationProperty("sensor.accelerometer.maxDelay", "100000");
3089 addConfigurationProperty("sensor.accelerometer.minDelay", "5000");
3090 addConfigurationProperty("sensor.accelerometer.power", "1.5");
3091}
3092
3093void SensorInputMapperTest::setGyroProperties() {
3094 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 3, InputDeviceSensorType::GYROSCOPE,
3095 /* sensorDataIndex */ 0);
3096 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 4, InputDeviceSensorType::GYROSCOPE,
3097 /* sensorDataIndex */ 1);
3098 mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 5, InputDeviceSensorType::GYROSCOPE,
3099 /* sensorDataIndex */ 2);
3100 mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP);
3101 addConfigurationProperty("sensor.gyroscope.reportingMode", "0");
3102 addConfigurationProperty("sensor.gyroscope.maxDelay", "100000");
3103 addConfigurationProperty("sensor.gyroscope.minDelay", "5000");
3104 addConfigurationProperty("sensor.gyroscope.power", "0.8");
3105}
3106
3107TEST_F(SensorInputMapperTest, GetSources) {
Arpit Singhfb706c32023-04-26 15:07:55 +00003108 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003109
3110 ASSERT_EQ(static_cast<uint32_t>(AINPUT_SOURCE_SENSOR), mapper.getSources());
3111}
3112
3113TEST_F(SensorInputMapperTest, ProcessAccelerometerSensor) {
3114 setAccelProperties();
3115 prepareAccelAxes();
Arpit Singhfb706c32023-04-26 15:07:55 +00003116 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003117
3118 ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::ACCELEROMETER,
3119 std::chrono::microseconds(10000),
3120 std::chrono::microseconds(0)));
Chris Yee14523a2020-12-19 13:46:00 -08003121 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003122 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, 20000);
3123 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, -20000);
3124 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Z, 40000);
3125 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000);
3126 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Chris Yef59a2f42020-10-16 12:55:26 -07003127
3128 NotifySensorArgs args;
3129 std::vector<float> values = {20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT,
3130 -20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT,
3131 40000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT};
3132
3133 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args));
3134 ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR);
3135 ASSERT_EQ(args.deviceId, DEVICE_ID);
3136 ASSERT_EQ(args.sensorType, InputDeviceSensorType::ACCELEROMETER);
3137 ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH);
3138 ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME);
3139 ASSERT_EQ(args.values, values);
3140 mapper.flushSensor(InputDeviceSensorType::ACCELEROMETER);
3141}
3142
3143TEST_F(SensorInputMapperTest, ProcessGyroscopeSensor) {
3144 setGyroProperties();
3145 prepareGyroAxes();
Arpit Singhfb706c32023-04-26 15:07:55 +00003146 SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
Chris Yef59a2f42020-10-16 12:55:26 -07003147
3148 ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::GYROSCOPE,
3149 std::chrono::microseconds(10000),
3150 std::chrono::microseconds(0)));
Chris Yee14523a2020-12-19 13:46:00 -08003151 ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003152 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RX, 20000);
3153 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RY, -20000);
3154 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RZ, 40000);
3155 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000);
3156 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Chris Yef59a2f42020-10-16 12:55:26 -07003157
3158 NotifySensorArgs args;
3159 std::vector<float> values = {20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT,
3160 -20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT,
3161 40000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT};
3162
3163 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args));
3164 ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR);
3165 ASSERT_EQ(args.deviceId, DEVICE_ID);
3166 ASSERT_EQ(args.sensorType, InputDeviceSensorType::GYROSCOPE);
3167 ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH);
3168 ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME);
3169 ASSERT_EQ(args.values, values);
3170 mapper.flushSensor(InputDeviceSensorType::GYROSCOPE);
3171}
3172
Michael Wrightd02c5b62014-02-10 15:10:22 -08003173// --- KeyboardInputMapperTest ---
3174
3175class KeyboardInputMapperTest : public InputMapperTest {
3176protected:
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003177 void SetUp() override {
3178 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
3179 InputDeviceClass::ALPHAKEY);
3180 }
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003181 const std::string UNIQUE_ID = "local:0";
Zixuan Qufecb6062022-11-12 04:44:31 +00003182 const KeyboardLayoutInfo DEVICE_KEYBOARD_LAYOUT_INFO = KeyboardLayoutInfo("en-US", "qwerty");
Michael Wrighta9cf4192022-12-01 23:46:39 +00003183 void prepareDisplay(ui::Rotation orientation);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003184
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003185 void testDPadKeyRotation(KeyboardInputMapper& mapper, int32_t originalScanCode,
Arthur Hung2c9a3342019-07-23 14:18:59 +08003186 int32_t originalKeyCode, int32_t rotatedKeyCode,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003187 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003188};
3189
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003190/* Similar to setDisplayInfoAndReconfigure, but pre-populates all parameters except for the
3191 * orientation.
3192 */
Michael Wrighta9cf4192022-12-01 23:46:39 +00003193void KeyboardInputMapperTest::prepareDisplay(ui::Rotation orientation) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003194 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
3195 NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003196}
3197
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003198void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper& mapper,
Arthur Hung2c9a3342019-07-23 14:18:59 +08003199 int32_t originalScanCode, int32_t originalKeyCode,
Linnan Li13bf76a2024-05-05 19:18:02 +08003200 int32_t rotatedKeyCode,
3201 ui::LogicalDisplayId displayId) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003202 NotifyKeyArgs args;
3203
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003204 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003205 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3206 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3207 ASSERT_EQ(originalScanCode, args.scanCode);
3208 ASSERT_EQ(rotatedKeyCode, args.keyCode);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003209 ASSERT_EQ(displayId, args.displayId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003210
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003211 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003212 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3213 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3214 ASSERT_EQ(originalScanCode, args.scanCode);
3215 ASSERT_EQ(rotatedKeyCode, args.keyCode);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003216 ASSERT_EQ(displayId, args.displayId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003217}
3218
Michael Wrightd02c5b62014-02-10 15:10:22 -08003219TEST_F(KeyboardInputMapperTest, GetSources) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003220 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003221 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003222
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003223 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003224}
3225
3226TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) {
3227 const int32_t USAGE_A = 0x070004;
3228 const int32_t USAGE_UNKNOWN = 0x07ffff;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003229 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3230 mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
Chris Yea52ade12020-08-27 16:49:20 -07003231 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, POLICY_FLAG_WAKE);
3232 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, POLICY_FLAG_WAKE);
3233 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, POLICY_FLAG_WAKE);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003234
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003235 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003236 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003237 // Initial metastate is AMETA_NONE.
3238 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003239
3240 // Key down by scan code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003241 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003242 NotifyKeyArgs args;
3243 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3244 ASSERT_EQ(DEVICE_ID, args.deviceId);
3245 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3246 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3247 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3248 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3249 ASSERT_EQ(KEY_HOME, args.scanCode);
3250 ASSERT_EQ(AMETA_NONE, args.metaState);
3251 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3252 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3253 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3254
3255 // Key up by scan code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003256 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003257 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3258 ASSERT_EQ(DEVICE_ID, args.deviceId);
3259 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3260 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3261 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3262 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3263 ASSERT_EQ(KEY_HOME, args.scanCode);
3264 ASSERT_EQ(AMETA_NONE, args.metaState);
3265 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3266 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3267 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3268
3269 // Key down by usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003270 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A);
3271 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, 0, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003272 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3273 ASSERT_EQ(DEVICE_ID, args.deviceId);
3274 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3275 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3276 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3277 ASSERT_EQ(AKEYCODE_A, args.keyCode);
3278 ASSERT_EQ(0, args.scanCode);
3279 ASSERT_EQ(AMETA_NONE, args.metaState);
3280 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3281 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3282 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3283
3284 // Key up by usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003285 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A);
3286 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003287 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3288 ASSERT_EQ(DEVICE_ID, args.deviceId);
3289 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3290 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3291 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3292 ASSERT_EQ(AKEYCODE_A, args.keyCode);
3293 ASSERT_EQ(0, args.scanCode);
3294 ASSERT_EQ(AMETA_NONE, args.metaState);
3295 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3296 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
3297 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3298
3299 // Key down with unknown scan code or usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003300 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
3301 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003302 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3303 ASSERT_EQ(DEVICE_ID, args.deviceId);
3304 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3305 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3306 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3307 ASSERT_EQ(0, args.keyCode);
3308 ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
3309 ASSERT_EQ(AMETA_NONE, args.metaState);
3310 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3311 ASSERT_EQ(0U, args.policyFlags);
3312 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3313
3314 // Key up with unknown scan code or usage code.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003315 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
3316 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_UNKNOWN, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003317 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3318 ASSERT_EQ(DEVICE_ID, args.deviceId);
3319 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3320 ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
3321 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3322 ASSERT_EQ(0, args.keyCode);
3323 ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
3324 ASSERT_EQ(AMETA_NONE, args.metaState);
3325 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3326 ASSERT_EQ(0U, args.policyFlags);
3327 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
3328}
3329
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003330TEST_F(KeyboardInputMapperTest, Process_KeyRemapping) {
3331 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
3332 mFakeEventHub->addKey(EVENTHUB_ID, KEY_B, 0, AKEYCODE_B, 0);
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003333
3334 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003335 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003336
Linnan Lie5657f22024-09-13 21:54:37 +08003337 mFakeEventHub->setKeyRemapping(EVENTHUB_ID, {{AKEYCODE_A, AKEYCODE_B}});
Vaibhav Devmuraricbba14c2022-10-10 16:54:49 +00003338 // Key down by scan code.
3339 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_A, 1);
3340 NotifyKeyArgs args;
3341 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3342 ASSERT_EQ(AKEYCODE_B, args.keyCode);
3343
3344 // Key up by scan code.
3345 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 0);
3346 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3347 ASSERT_EQ(AKEYCODE_B, args.keyCode);
3348}
3349
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003350/**
3351 * Ensure that the readTime is set to the time when the EV_KEY is received.
3352 */
3353TEST_F(KeyboardInputMapperTest, Process_SendsReadTime) {
3354 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3355
3356 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003357 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003358 NotifyKeyArgs args;
3359
3360 // Key down
Harry Cutts33476232023-01-30 19:57:29 +00003361 process(mapper, ARBITRARY_TIME, /*readTime=*/12, EV_KEY, KEY_HOME, 1);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003362 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3363 ASSERT_EQ(12, args.readTime);
3364
3365 // Key up
Harry Cutts33476232023-01-30 19:57:29 +00003366 process(mapper, ARBITRARY_TIME, /*readTime=*/15, EV_KEY, KEY_HOME, 1);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003367 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3368 ASSERT_EQ(15, args.readTime);
3369}
3370
Michael Wrightd02c5b62014-02-10 15:10:22 -08003371TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003372 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFTSHIFT, 0, AKEYCODE_SHIFT_LEFT, 0);
3373 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
Chris Yea52ade12020-08-27 16:49:20 -07003374 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 0);
3375 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0);
3376 mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003377
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003378 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003379 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003380
Arthur Hung95f68612022-04-07 14:08:22 +08003381 // Initial metastate is AMETA_NONE.
3382 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003383
3384 // Metakey down.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003385 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003386 NotifyKeyArgs args;
3387 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3388 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003389 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
arthurhungdcef2dc2020-08-11 14:47:50 +08003390 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003391
3392 // Key down.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003393 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003394 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3395 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003396 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003397
3398 // Key up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003399 process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_KEY, KEY_A, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003400 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3401 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003402 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003403
3404 // Metakey up.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003405 process(mapper, ARBITRARY_TIME + 3, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003406 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3407 ASSERT_EQ(AMETA_NONE, args.metaState);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003408 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
arthurhungdcef2dc2020-08-11 14:47:50 +08003409 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003410}
3411
3412TEST_F(KeyboardInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateDPad) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003413 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3414 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3415 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3416 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003417
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003418 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003419 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003420
Michael Wrighta9cf4192022-12-01 23:46:39 +00003421 prepareDisplay(ui::ROTATION_90);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003422 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3423 KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
3424 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3425 KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
3426 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3427 KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
3428 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
3429 KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
3430}
3431
3432TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003433 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3434 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3435 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3436 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003437
Michael Wrightd02c5b62014-02-10 15:10:22 -08003438 addConfigurationProperty("keyboard.orientationAware", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003439 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003440 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003441
Michael Wrighta9cf4192022-12-01 23:46:39 +00003442 prepareDisplay(ui::ROTATION_0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003443 ASSERT_NO_FATAL_FAILURE(
3444 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
3445 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3446 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3447 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3448 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3449 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3450 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003451
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003452 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003453 prepareDisplay(ui::ROTATION_90);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003454 ASSERT_NO_FATAL_FAILURE(
3455 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3456 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3457 AKEYCODE_DPAD_UP, DISPLAY_ID));
3458 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3459 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3460 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3461 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003462
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003463 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003464 prepareDisplay(ui::ROTATION_180);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003465 ASSERT_NO_FATAL_FAILURE(
3466 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3467 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3468 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3469 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3470 AKEYCODE_DPAD_UP, DISPLAY_ID));
3471 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3472 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003473
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003474 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003475 prepareDisplay(ui::ROTATION_270);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003476 ASSERT_NO_FATAL_FAILURE(
3477 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3478 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3479 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3480 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3481 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3482 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3483 AKEYCODE_DPAD_UP, DISPLAY_ID));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003484
3485 // Special case: if orientation changes while key is down, we still emit the same keycode
3486 // in the key up as we did in the key down.
3487 NotifyKeyArgs args;
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003488 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003489 prepareDisplay(ui::ROTATION_270);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003490 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003491 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3492 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3493 ASSERT_EQ(KEY_UP, args.scanCode);
3494 ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
3495
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003496 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003497 prepareDisplay(ui::ROTATION_180);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003498 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003499 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3500 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3501 ASSERT_EQ(KEY_UP, args.scanCode);
3502 ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
3503}
3504
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003505TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_NotOrientationAware) {
3506 // If the keyboard is not orientation aware,
3507 // key events should not be associated with a specific display id
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003508 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003509
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003510 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003511 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003512 NotifyKeyArgs args;
3513
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003514 // Display id should be LogicalDisplayId::INVALID without any display configuration.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003515 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003516 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003517 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003518 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003519 ASSERT_EQ(ui::LogicalDisplayId::INVALID, args.displayId);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003520
Michael Wrighta9cf4192022-12-01 23:46:39 +00003521 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003522 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003523 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003524 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003525 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003526 ASSERT_EQ(ui::LogicalDisplayId::INVALID, args.displayId);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003527}
3528
3529TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_OrientationAware) {
3530 // If the keyboard is orientation aware,
3531 // key events should be associated with the internal viewport
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003532 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003533
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003534 addConfigurationProperty("keyboard.orientationAware", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003535 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003536 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003537 NotifyKeyArgs args;
3538
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003539 // Display id should be LogicalDisplayId::INVALID without any display configuration.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003540 // ^--- already checked by the previous test
3541
Michael Wrighta9cf4192022-12-01 23:46:39 +00003542 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003543 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003544 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003545 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003546 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003547 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3548 ASSERT_EQ(DISPLAY_ID, args.displayId);
3549
Linnan Li13bf76a2024-05-05 19:18:02 +08003550 constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003551 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00003552 setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003553 UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003554 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003555 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003556 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01003557 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3558 ASSERT_EQ(newDisplayId, args.displayId);
3559}
3560
Michael Wrightd02c5b62014-02-10 15:10:22 -08003561TEST_F(KeyboardInputMapperTest, GetKeyCodeState) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003562 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003563 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003564
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003565 mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003566 ASSERT_EQ(1, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003567
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003568 mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003569 ASSERT_EQ(0, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003570}
3571
Philip Junker4af3b3d2021-12-14 10:36:55 +01003572TEST_F(KeyboardInputMapperTest, GetKeyCodeForKeyLocation) {
3573 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003574 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Philip Junker4af3b3d2021-12-14 10:36:55 +01003575
3576 mFakeEventHub->addKeyCodeMapping(EVENTHUB_ID, AKEYCODE_Y, AKEYCODE_Z);
3577 ASSERT_EQ(AKEYCODE_Z, mapper.getKeyCodeForKeyLocation(AKEYCODE_Y))
3578 << "If a mapping is available, the result is equal to the mapping";
3579
3580 ASSERT_EQ(AKEYCODE_A, mapper.getKeyCodeForKeyLocation(AKEYCODE_A))
3581 << "If no mapping is available, the result is the key location";
3582}
3583
Michael Wrightd02c5b62014-02-10 15:10:22 -08003584TEST_F(KeyboardInputMapperTest, GetScanCodeState) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003585 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003586 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003587
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003588 mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 1);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003589 ASSERT_EQ(1, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003590
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003591 mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 0);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003592 ASSERT_EQ(0, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003593}
3594
3595TEST_F(KeyboardInputMapperTest, MarkSupportedKeyCodes) {
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003596 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003597 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003598
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003599 mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003600
Michael Wrightd02c5b62014-02-10 15:10:22 -08003601 uint8_t flags[2] = { 0, 0 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07003602 ASSERT_TRUE(mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_A, AKEYCODE_B}, flags));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003603 ASSERT_TRUE(flags[0]);
3604 ASSERT_FALSE(flags[1]);
3605}
3606
3607TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003608 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3609 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3610 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3611 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3612 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3613 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003614
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003615 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003616 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003617 // Initial metastate is AMETA_NONE.
3618 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003619
3620 // Initialization should have turned all of the lights off.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003621 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3622 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3623 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003624
3625 // Toggle caps lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003626 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3627 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003628 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3629 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3630 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003631 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003632
3633 // Toggle num lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003634 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3635 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003636 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3637 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3638 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003639 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003640
3641 // Toggle caps lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003642 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3643 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003644 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3645 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3646 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003647 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003648
3649 // Toggle scroll lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003650 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3651 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003652 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3653 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3654 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003655 ASSERT_EQ(AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003656
3657 // Toggle num lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003658 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3659 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003660 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3661 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3662 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003663 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003664
3665 // Toggle scroll lock off.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003666 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3667 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003668 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3669 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3670 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003671 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003672}
3673
Arthur Hung2c9a3342019-07-23 14:18:59 +08003674TEST_F(KeyboardInputMapperTest, Configure_AssignsDisplayPort) {
3675 // keyboard 1.
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003676 mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3677 mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3678 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3679 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003680
3681 // keyboard 2.
3682 const std::string USB2 = "USB2";
arthurhungdcef2dc2020-08-11 14:47:50 +08003683 const std::string DEVICE_NAME2 = "KEYBOARD2";
Arthur Hung2c9a3342019-07-23 14:18:59 +08003684 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003685 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
arthurhungdcef2dc2020-08-11 14:47:50 +08003686 std::shared_ptr<InputDevice> device2 =
3687 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
Dominik Laskowski2f01d772022-03-23 16:01:29 -07003688 ftl::Flags<InputDeviceClass>(0));
arthurhungdcef2dc2020-08-11 14:47:50 +08003689
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08003690 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
3691 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
3692 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
3693 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003694
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003695 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003696 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003697
Arpit Singh67ca6842023-04-26 14:43:16 +00003698 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08003699 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003700 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3701 mFakePolicy
3702 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003703 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003704 std::list<NotifyArgs> unused =
3705 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003706 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003707 unused += device2->reset(ARBITRARY_TIME);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003708
3709 // Prepared displays and associated info.
3710 constexpr uint8_t hdmi1 = 0;
3711 constexpr uint8_t hdmi2 = 1;
3712 const std::string SECONDARY_UNIQUE_ID = "local:1";
3713
3714 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
3715 mFakePolicy->addInputPortAssociation(USB2, hdmi2);
3716
3717 // No associated display viewport found, should disable the device.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003718 unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003719 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003720 ASSERT_FALSE(device2->isEnabled());
3721
3722 // Prepare second display.
Linnan Li13bf76a2024-05-05 19:18:02 +08003723 constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
Michael Wrighta9cf4192022-12-01 23:46:39 +00003724 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003725 UNIQUE_ID, hdmi1, ViewportType::INTERNAL);
Michael Wrighta9cf4192022-12-01 23:46:39 +00003726 setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Michael Wrightfe3de7d2020-07-02 19:05:30 +01003727 SECONDARY_UNIQUE_ID, hdmi2, ViewportType::EXTERNAL);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003728 // Default device will reconfigure above, need additional reconfiguration for another device.
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003729 unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003730 InputReaderConfiguration::Change::DISPLAY_INFO);
Arthur Hung2c9a3342019-07-23 14:18:59 +08003731
3732 // Device should be enabled after the associated display is found.
3733 ASSERT_TRUE(mDevice->isEnabled());
3734 ASSERT_TRUE(device2->isEnabled());
3735
3736 // Test pad key events
3737 ASSERT_NO_FATAL_FAILURE(
3738 testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
3739 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3740 AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
3741 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3742 AKEYCODE_DPAD_DOWN, DISPLAY_ID));
3743 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3744 AKEYCODE_DPAD_LEFT, DISPLAY_ID));
3745
3746 ASSERT_NO_FATAL_FAILURE(
3747 testDPadKeyRotation(mapper2, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, newDisplayId));
3748 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
3749 AKEYCODE_DPAD_RIGHT, newDisplayId));
3750 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_DOWN, AKEYCODE_DPAD_DOWN,
3751 AKEYCODE_DPAD_DOWN, newDisplayId));
3752 ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_LEFT, AKEYCODE_DPAD_LEFT,
3753 AKEYCODE_DPAD_LEFT, newDisplayId));
3754}
Michael Wrightd02c5b62014-02-10 15:10:22 -08003755
arthurhungc903df12020-08-11 15:08:42 +08003756TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleAfterReattach) {
3757 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3758 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3759 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3760 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3761 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3762 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3763
3764 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003765 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003766 // Initial metastate is AMETA_NONE.
3767 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
arthurhungc903df12020-08-11 15:08:42 +08003768
3769 // Initialization should have turned all of the lights off.
3770 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3771 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3772 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3773
3774 // Toggle caps lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003775 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3776 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003777 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3778 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
3779
3780 // Toggle num lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003781 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3782 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003783 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3784 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
3785
3786 // Toggle scroll lock on.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00003787 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3788 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
arthurhungc903df12020-08-11 15:08:42 +08003789 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3790 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
3791
3792 mFakeEventHub->removeDevice(EVENTHUB_ID);
3793 mReader->loopOnce();
3794
3795 // keyboard 2 should default toggle keys.
3796 const std::string USB2 = "USB2";
3797 const std::string DEVICE_NAME2 = "KEYBOARD2";
3798 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
3799 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
3800 std::shared_ptr<InputDevice> device2 =
3801 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
Dominik Laskowski2f01d772022-03-23 16:01:29 -07003802 ftl::Flags<InputDeviceClass>(0));
arthurhungc903df12020-08-11 15:08:42 +08003803 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3804 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
3805 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3806 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3807 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3808 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3809
Arpit Singh67ca6842023-04-26 14:43:16 +00003810 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
arthurhung6fe95782020-10-05 22:41:16 +08003811 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003812 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3813 mFakePolicy
3814 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003815 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003816 std::list<NotifyArgs> unused =
3817 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003818 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003819 unused += device2->reset(ARBITRARY_TIME);
arthurhungc903df12020-08-11 15:08:42 +08003820
3821 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_CAPSL));
3822 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_NUML));
3823 ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_SCROLLL));
arthurhung6fe95782020-10-05 22:41:16 +08003824 ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON,
3825 mapper2.getMetaState());
arthurhungc903df12020-08-11 15:08:42 +08003826}
3827
Arthur Hungcb40a002021-08-03 14:31:01 +00003828TEST_F(KeyboardInputMapperTest, Process_toggleCapsLockState) {
3829 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3830 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3831 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3832
3833 // Suppose we have two mappers. (DPAD + KEYBOARD)
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003834 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD);
Arthur Hungcb40a002021-08-03 14:31:01 +00003835 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003836 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung95f68612022-04-07 14:08:22 +08003837 // Initial metastate is AMETA_NONE.
3838 ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
Arthur Hungcb40a002021-08-03 14:31:01 +00003839
3840 mReader->toggleCapsLockState(DEVICE_ID);
3841 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
3842}
3843
Arthur Hungfb3cc112022-04-13 07:39:50 +00003844TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleInMultiDevices) {
3845 // keyboard 1.
3846 mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3847 mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
3848 mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3849 mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3850 mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3851 mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3852
3853 KeyboardInputMapper& mapper1 =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003854 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hungfb3cc112022-04-13 07:39:50 +00003855
3856 // keyboard 2.
3857 const std::string USB2 = "USB2";
3858 const std::string DEVICE_NAME2 = "KEYBOARD2";
3859 constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
3860 constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
3861 std::shared_ptr<InputDevice> device2 =
3862 newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
3863 ftl::Flags<InputDeviceClass>(0));
3864 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
3865 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
3866 mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
3867 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
3868 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
3869 mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
3870
Arpit Singh67ca6842023-04-26 14:43:16 +00003871 device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
Arthur Hungfb3cc112022-04-13 07:39:50 +00003872 KeyboardInputMapper& mapper2 =
Arpit Singh67ca6842023-04-26 14:43:16 +00003873 device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
3874 mFakePolicy
3875 ->getReaderConfiguration(),
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003876 AINPUT_SOURCE_KEYBOARD);
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003877 std::list<NotifyArgs> unused =
3878 device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003879 /*changes=*/{});
Siarhei Vishniakou2935db72022-09-22 13:35:22 -07003880 unused += device2->reset(ARBITRARY_TIME);
Arthur Hungfb3cc112022-04-13 07:39:50 +00003881
Arthur Hung95f68612022-04-07 14:08:22 +08003882 // Initial metastate is AMETA_NONE.
3883 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
3884 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
3885
3886 // Toggle num lock on and off.
3887 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3888 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
Arthur Hungfb3cc112022-04-13 07:39:50 +00003889 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3890 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper1.getMetaState());
3891 ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper2.getMetaState());
3892
3893 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
3894 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
3895 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
3896 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
3897 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
3898
3899 // Toggle caps lock on and off.
3900 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3901 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
3902 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3903 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper1.getMetaState());
3904 ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper2.getMetaState());
3905
3906 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
3907 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
3908 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
3909 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
3910 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
3911
3912 // Toggle scroll lock on and off.
3913 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3914 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
3915 ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3916 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper1.getMetaState());
3917 ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper2.getMetaState());
3918
3919 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
3920 process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
3921 ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
3922 ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
3923 ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
3924}
3925
Arthur Hung2141d542022-08-23 07:45:21 +00003926TEST_F(KeyboardInputMapperTest, Process_DisabledDevice) {
3927 const int32_t USAGE_A = 0x070004;
3928 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
3929 mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
3930
3931 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003932 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Arthur Hung2141d542022-08-23 07:45:21 +00003933 // Key down by scan code.
3934 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
3935 NotifyKeyArgs args;
3936 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3937 ASSERT_EQ(DEVICE_ID, args.deviceId);
3938 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
3939 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
3940 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
3941 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3942 ASSERT_EQ(KEY_HOME, args.scanCode);
3943 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
3944
3945 // Disable device, it should synthesize cancellation events for down events.
3946 mFakePolicy->addDisabledDevice(DEVICE_ID);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003947 configureDevice(InputReaderConfiguration::Change::ENABLED_STATE);
Arthur Hung2141d542022-08-23 07:45:21 +00003948
3949 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
3950 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
3951 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
3952 ASSERT_EQ(KEY_HOME, args.scanCode);
3953 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_CANCELED, args.flags);
3954}
3955
Zixuan Qufecb6062022-11-12 04:44:31 +00003956TEST_F(KeyboardInputMapperTest, Configure_AssignKeyboardLayoutInfo) {
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003957 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Zixuan Qufecb6062022-11-12 04:44:31 +00003958 std::list<NotifyArgs> unused =
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003959 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
3960 /*changes=*/{});
Zixuan Qufecb6062022-11-12 04:44:31 +00003961
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +00003962 uint32_t generation = mReader->getContext()->getGeneration();
Zixuan Qufecb6062022-11-12 04:44:31 +00003963 mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
3964
3965 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003966 InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
Zixuan Qufecb6062022-11-12 04:44:31 +00003967
3968 InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
3969 ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.languageTag,
3970 deviceInfo.getKeyboardLayoutInfo()->languageTag);
3971 ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.layoutType,
3972 deviceInfo.getKeyboardLayoutInfo()->layoutType);
Vaibhav Devmurari0a6fee82023-04-11 18:53:04 +00003973 ASSERT_TRUE(mReader->getContext()->getGeneration() != generation);
3974
3975 // Call change layout association with the same values: Generation shouldn't change
3976 generation = mReader->getContext()->getGeneration();
3977 mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
3978 unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
3979 InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
3980 ASSERT_TRUE(mReader->getContext()->getGeneration() == generation);
Zixuan Qufecb6062022-11-12 04:44:31 +00003981}
3982
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00003983TEST_F(KeyboardInputMapperTest, LayoutInfoCorrectlyMapped) {
3984 mFakeEventHub->setRawLayoutInfo(EVENTHUB_ID,
3985 RawLayoutInfo{.languageTag = "en", .layoutType = "extended"});
3986
3987 // Configuration
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003988 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00003989 InputReaderConfiguration config;
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00003990 std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +00003991
3992 ASSERT_EQ("en", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->languageTag);
3993 ASSERT_EQ("extended", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->layoutType);
3994}
3995
Justin Chung71ddb432023-03-27 04:29:07 +00003996TEST_F(KeyboardInputMapperTest, Process_GesureEventToSetFlagKeepTouchMode) {
3997 mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, POLICY_FLAG_GESTURE);
3998 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00003999 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Justin Chung71ddb432023-03-27 04:29:07 +00004000 NotifyKeyArgs args;
4001
4002 // Key down
4003 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFT, 1);
4004 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4005 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_KEEP_TOUCH_MODE, args.flags);
4006}
4007
Prabir Pradhan38636652024-07-23 21:59:36 +00004008/**
4009 * When there is more than one KeyboardInputMapper for an InputDevice, each mapper should produce
4010 * events that use the shared keyboard source across all mappers. This is to ensure that each
4011 * input device generates key events in a consistent manner, regardless of which mapper produces
4012 * the event.
4013 */
4014TEST_F(KeyboardInputMapperTest, UsesSharedKeyboardSource) {
4015 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4016
4017 // Add a mapper with SOURCE_KEYBOARD
4018 KeyboardInputMapper& keyboardMapper =
4019 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
4020
4021 process(keyboardMapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1);
4022 ASSERT_NO_FATAL_FAILURE(
4023 mFakeListener->assertNotifyKeyWasCalled(WithSource(AINPUT_SOURCE_KEYBOARD)));
4024 process(keyboardMapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0);
4025 ASSERT_NO_FATAL_FAILURE(
4026 mFakeListener->assertNotifyKeyWasCalled(WithSource(AINPUT_SOURCE_KEYBOARD)));
4027
4028 // Add a mapper with SOURCE_DPAD
4029 KeyboardInputMapper& dpadMapper =
4030 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD);
4031 for (auto* mapper : {&keyboardMapper, &dpadMapper}) {
4032 process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1);
4033 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
4034 WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD)));
4035 process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0);
4036 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
4037 WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD)));
4038 }
4039
4040 // Add a mapper with SOURCE_GAMEPAD
4041 KeyboardInputMapper& gamepadMapper =
4042 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_GAMEPAD);
4043 for (auto* mapper : {&keyboardMapper, &dpadMapper, &gamepadMapper}) {
4044 process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1);
4045 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
4046 WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD)));
4047 process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0);
4048 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
4049 WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD)));
4050 }
4051}
4052
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004053// --- KeyboardInputMapperTest_ExternalAlphabeticDevice ---
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004054
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004055class KeyboardInputMapperTest_ExternalAlphabeticDevice : public InputMapperTest {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004056protected:
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004057 void SetUp() override {
4058 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
4059 InputDeviceClass::ALPHAKEY | InputDeviceClass::EXTERNAL);
4060 }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004061};
4062
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004063// --- KeyboardInputMapperTest_ExternalNonAlphabeticDevice ---
4064
4065class KeyboardInputMapperTest_ExternalNonAlphabeticDevice : public InputMapperTest {
4066protected:
4067 void SetUp() override {
4068 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
4069 InputDeviceClass::EXTERNAL);
4070 }
4071};
4072
4073TEST_F(KeyboardInputMapperTest_ExternalAlphabeticDevice, WakeBehavior_AlphabeticKeyboard) {
Vaibhav Devmurari16257862023-03-06 10:06:32 +00004074 // For external devices, keys will trigger wake on key down. Media keys should also trigger
4075 // wake if triggered from external devices.
Powei Fengd041c5d2019-05-03 17:11:33 -07004076
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004077 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, 0);
4078 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
4079 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
4080 POLICY_FLAG_WAKE);
Powei Fengd041c5d2019-05-03 17:11:33 -07004081
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004082 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004083 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Powei Fengd041c5d2019-05-03 17:11:33 -07004084
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004085 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004086 NotifyKeyArgs args;
4087 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4088 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4089
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004090 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004091 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4092 ASSERT_EQ(uint32_t(0), args.policyFlags);
4093
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004094 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004095 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
Vaibhav Devmurari16257862023-03-06 10:06:32 +00004096 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
Powei Fengd041c5d2019-05-03 17:11:33 -07004097
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004098 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004099 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4100 ASSERT_EQ(uint32_t(0), args.policyFlags);
4101
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004102 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004103 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4104 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4105
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004106 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004107 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4108 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4109}
4110
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004111TEST_F(KeyboardInputMapperTest_ExternalNonAlphabeticDevice, WakeBehavior_NonAlphabeticKeyboard) {
Vaibhav Devmurari2681a812024-01-11 00:15:35 +00004112 // For external devices, keys will trigger wake on key down. Media keys should not trigger
4113 // wake if triggered from external non-alphaebtic keyboard (e.g. headsets).
4114
4115 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
4116 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
4117 POLICY_FLAG_WAKE);
4118
4119 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004120 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Vaibhav Devmurari2681a812024-01-11 00:15:35 +00004121
4122 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
4123 NotifyKeyArgs args;
4124 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4125 ASSERT_EQ(uint32_t(0), args.policyFlags);
4126
4127 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
4128 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4129 ASSERT_EQ(uint32_t(0), args.policyFlags);
4130
4131 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1);
4132 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4133 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4134
4135 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0);
4136 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4137 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4138}
4139
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004140TEST_F(KeyboardInputMapperTest_ExternalAlphabeticDevice, DoNotWakeByDefaultBehavior) {
Powei Fengd041c5d2019-05-03 17:11:33 -07004141 // Tv Remote key's wake behavior is prescribed by the keylayout file.
Powei Fengd041c5d2019-05-03 17:11:33 -07004142
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004143 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4144 mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
4145 mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, POLICY_FLAG_WAKE);
Powei Fengd041c5d2019-05-03 17:11:33 -07004146
Powei Fengd041c5d2019-05-03 17:11:33 -07004147 addConfigurationProperty("keyboard.doNotWakeByDefault", "1");
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004148 KeyboardInputMapper& mapper =
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +00004149 constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
Powei Fengd041c5d2019-05-03 17:11:33 -07004150
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004151 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004152 NotifyKeyArgs args;
4153 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4154 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4155
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004156 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004157 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4158 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4159
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004160 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_DOWN, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004161 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4162 ASSERT_EQ(uint32_t(0), args.policyFlags);
4163
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004164 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_DOWN, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004165 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4166 ASSERT_EQ(uint32_t(0), args.policyFlags);
4167
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004168 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
Powei Fengd041c5d2019-05-03 17:11:33 -07004169 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4170 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4171
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00004172 process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
Powei Fengd041c5d2019-05-03 17:11:33 -07004173 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4174 ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
4175}
4176
Michael Wrightd02c5b62014-02-10 15:10:22 -08004177// --- TouchInputMapperTest ---
4178
4179class TouchInputMapperTest : public InputMapperTest {
4180protected:
4181 static const int32_t RAW_X_MIN;
4182 static const int32_t RAW_X_MAX;
4183 static const int32_t RAW_Y_MIN;
4184 static const int32_t RAW_Y_MAX;
4185 static const int32_t RAW_TOUCH_MIN;
4186 static const int32_t RAW_TOUCH_MAX;
4187 static const int32_t RAW_TOOL_MIN;
4188 static const int32_t RAW_TOOL_MAX;
4189 static const int32_t RAW_PRESSURE_MIN;
4190 static const int32_t RAW_PRESSURE_MAX;
4191 static const int32_t RAW_ORIENTATION_MIN;
4192 static const int32_t RAW_ORIENTATION_MAX;
4193 static const int32_t RAW_DISTANCE_MIN;
4194 static const int32_t RAW_DISTANCE_MAX;
4195 static const int32_t RAW_TILT_MIN;
4196 static const int32_t RAW_TILT_MAX;
4197 static const int32_t RAW_ID_MIN;
4198 static const int32_t RAW_ID_MAX;
4199 static const int32_t RAW_SLOT_MIN;
4200 static const int32_t RAW_SLOT_MAX;
4201 static const float X_PRECISION;
4202 static const float Y_PRECISION;
Santos Cordonfa5cf462017-04-05 10:37:00 -07004203 static const float X_PRECISION_VIRTUAL;
4204 static const float Y_PRECISION_VIRTUAL;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004205
4206 static const float GEOMETRIC_SCALE;
Jason Gerecke489fda82012-09-07 17:19:40 -07004207 static const TouchAffineTransformation AFFINE_TRANSFORM;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004208
4209 static const VirtualKeyDefinition VIRTUAL_KEYS[2];
4210
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07004211 const std::string UNIQUE_ID = "local:0";
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004212 const std::string SECONDARY_UNIQUE_ID = "local:1";
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07004213
Michael Wrightd02c5b62014-02-10 15:10:22 -08004214 enum Axes {
4215 POSITION = 1 << 0,
4216 TOUCH = 1 << 1,
4217 TOOL = 1 << 2,
4218 PRESSURE = 1 << 3,
4219 ORIENTATION = 1 << 4,
4220 MINOR = 1 << 5,
4221 ID = 1 << 6,
4222 DISTANCE = 1 << 7,
4223 TILT = 1 << 8,
4224 SLOT = 1 << 9,
4225 TOOL_TYPE = 1 << 10,
4226 };
4227
Michael Wrighta9cf4192022-12-01 23:46:39 +00004228 void prepareDisplay(ui::Rotation orientation, std::optional<uint8_t> port = NO_PORT);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004229 void prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port = NO_PORT);
Michael Wrighta9cf4192022-12-01 23:46:39 +00004230 void prepareVirtualDisplay(ui::Rotation orientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004231 void prepareVirtualKeys();
Jason Gerecke489fda82012-09-07 17:19:40 -07004232 void prepareLocationCalibration();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004233 int32_t toRawX(float displayX);
4234 int32_t toRawY(float displayY);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07004235 int32_t toRotatedRawX(float displayX);
4236 int32_t toRotatedRawY(float displayY);
Jason Gerecke489fda82012-09-07 17:19:40 -07004237 float toCookedX(float rawX, float rawY);
4238 float toCookedY(float rawX, float rawY);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004239 float toDisplayX(int32_t rawX);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004240 float toDisplayX(int32_t rawX, int32_t displayWidth);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004241 float toDisplayY(int32_t rawY);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004242 float toDisplayY(int32_t rawY, int32_t displayHeight);
4243
Michael Wrightd02c5b62014-02-10 15:10:22 -08004244};
4245
4246const int32_t TouchInputMapperTest::RAW_X_MIN = 25;
4247const int32_t TouchInputMapperTest::RAW_X_MAX = 1019;
4248const int32_t TouchInputMapperTest::RAW_Y_MIN = 30;
4249const int32_t TouchInputMapperTest::RAW_Y_MAX = 1009;
4250const int32_t TouchInputMapperTest::RAW_TOUCH_MIN = 0;
4251const int32_t TouchInputMapperTest::RAW_TOUCH_MAX = 31;
4252const int32_t TouchInputMapperTest::RAW_TOOL_MIN = 0;
4253const int32_t TouchInputMapperTest::RAW_TOOL_MAX = 15;
Michael Wrightaa449c92017-12-13 21:21:43 +00004254const int32_t TouchInputMapperTest::RAW_PRESSURE_MIN = 0;
4255const int32_t TouchInputMapperTest::RAW_PRESSURE_MAX = 255;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004256const int32_t TouchInputMapperTest::RAW_ORIENTATION_MIN = -7;
4257const int32_t TouchInputMapperTest::RAW_ORIENTATION_MAX = 7;
4258const int32_t TouchInputMapperTest::RAW_DISTANCE_MIN = 0;
4259const int32_t TouchInputMapperTest::RAW_DISTANCE_MAX = 7;
4260const int32_t TouchInputMapperTest::RAW_TILT_MIN = 0;
4261const int32_t TouchInputMapperTest::RAW_TILT_MAX = 150;
4262const int32_t TouchInputMapperTest::RAW_ID_MIN = 0;
4263const int32_t TouchInputMapperTest::RAW_ID_MAX = 9;
4264const int32_t TouchInputMapperTest::RAW_SLOT_MIN = 0;
4265const int32_t TouchInputMapperTest::RAW_SLOT_MAX = 9;
4266const float TouchInputMapperTest::X_PRECISION = float(RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH;
4267const float TouchInputMapperTest::Y_PRECISION = float(RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT;
Santos Cordonfa5cf462017-04-05 10:37:00 -07004268const float TouchInputMapperTest::X_PRECISION_VIRTUAL =
4269 float(RAW_X_MAX - RAW_X_MIN + 1) / VIRTUAL_DISPLAY_WIDTH;
4270const float TouchInputMapperTest::Y_PRECISION_VIRTUAL =
4271 float(RAW_Y_MAX - RAW_Y_MIN + 1) / VIRTUAL_DISPLAY_HEIGHT;
Jason Gerecke489fda82012-09-07 17:19:40 -07004272const TouchAffineTransformation TouchInputMapperTest::AFFINE_TRANSFORM =
4273 TouchAffineTransformation(1, -2, 3, -4, 5, -6);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004274
4275const float TouchInputMapperTest::GEOMETRIC_SCALE =
4276 avg(float(DISPLAY_WIDTH) / (RAW_X_MAX - RAW_X_MIN + 1),
4277 float(DISPLAY_HEIGHT) / (RAW_Y_MAX - RAW_Y_MIN + 1));
4278
4279const VirtualKeyDefinition TouchInputMapperTest::VIRTUAL_KEYS[2] = {
4280 { KEY_HOME, 60, DISPLAY_HEIGHT + 15, 20, 20 },
4281 { KEY_MENU, DISPLAY_HEIGHT - 60, DISPLAY_WIDTH + 15, 20, 20 },
4282};
4283
Michael Wrighta9cf4192022-12-01 23:46:39 +00004284void TouchInputMapperTest::prepareDisplay(ui::Rotation orientation, std::optional<uint8_t> port) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01004285 setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
4286 port, ViewportType::INTERNAL);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07004287}
4288
4289void TouchInputMapperTest::prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port) {
4290 setDisplayInfoAndReconfigure(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
Michael Wrighta9cf4192022-12-01 23:46:39 +00004291 ui::ROTATION_0, SECONDARY_UNIQUE_ID, port, type);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004292}
4293
Michael Wrighta9cf4192022-12-01 23:46:39 +00004294void TouchInputMapperTest::prepareVirtualDisplay(ui::Rotation orientation) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01004295 setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH, VIRTUAL_DISPLAY_HEIGHT,
4296 orientation, VIRTUAL_DISPLAY_UNIQUE_ID, NO_PORT,
4297 ViewportType::VIRTUAL);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004298}
4299
Michael Wrightd02c5b62014-02-10 15:10:22 -08004300void TouchInputMapperTest::prepareVirtualKeys() {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004301 mFakeEventHub->addVirtualKeyDefinition(EVENTHUB_ID, VIRTUAL_KEYS[0]);
4302 mFakeEventHub->addVirtualKeyDefinition(EVENTHUB_ID, VIRTUAL_KEYS[1]);
4303 mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
4304 mFakeEventHub->addKey(EVENTHUB_ID, KEY_MENU, 0, AKEYCODE_MENU, POLICY_FLAG_WAKE);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004305}
4306
Jason Gerecke489fda82012-09-07 17:19:40 -07004307void TouchInputMapperTest::prepareLocationCalibration() {
4308 mFakePolicy->setTouchAffineTransformation(AFFINE_TRANSFORM);
4309}
4310
Michael Wrightd02c5b62014-02-10 15:10:22 -08004311int32_t TouchInputMapperTest::toRawX(float displayX) {
4312 return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH + RAW_X_MIN);
4313}
4314
4315int32_t TouchInputMapperTest::toRawY(float displayY) {
4316 return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT + RAW_Y_MIN);
4317}
4318
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07004319int32_t TouchInputMapperTest::toRotatedRawX(float displayX) {
4320 return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_HEIGHT + RAW_X_MIN);
4321}
4322
4323int32_t TouchInputMapperTest::toRotatedRawY(float displayY) {
4324 return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_WIDTH + RAW_Y_MIN);
4325}
4326
Jason Gerecke489fda82012-09-07 17:19:40 -07004327float TouchInputMapperTest::toCookedX(float rawX, float rawY) {
4328 AFFINE_TRANSFORM.applyTo(rawX, rawY);
4329 return rawX;
4330}
4331
4332float TouchInputMapperTest::toCookedY(float rawX, float rawY) {
4333 AFFINE_TRANSFORM.applyTo(rawX, rawY);
4334 return rawY;
4335}
4336
Michael Wrightd02c5b62014-02-10 15:10:22 -08004337float TouchInputMapperTest::toDisplayX(int32_t rawX) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004338 return toDisplayX(rawX, DISPLAY_WIDTH);
4339}
4340
4341float TouchInputMapperTest::toDisplayX(int32_t rawX, int32_t displayWidth) {
4342 return float(rawX - RAW_X_MIN) * displayWidth / (RAW_X_MAX - RAW_X_MIN + 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004343}
4344
4345float TouchInputMapperTest::toDisplayY(int32_t rawY) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004346 return toDisplayY(rawY, DISPLAY_HEIGHT);
4347}
4348
4349float TouchInputMapperTest::toDisplayY(int32_t rawY, int32_t displayHeight) {
4350 return float(rawY - RAW_Y_MIN) * displayHeight / (RAW_Y_MAX - RAW_Y_MIN + 1);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004351}
4352
4353
4354// --- SingleTouchInputMapperTest ---
4355
4356class SingleTouchInputMapperTest : public TouchInputMapperTest {
4357protected:
4358 void prepareButtons();
4359 void prepareAxes(int axes);
4360
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004361 std::list<NotifyArgs> processDown(SingleTouchInputMapper& mapper, int32_t x, int32_t y);
4362 std::list<NotifyArgs> processMove(SingleTouchInputMapper& mapper, int32_t x, int32_t y);
4363 std::list<NotifyArgs> processUp(SingleTouchInputMapper& mappery);
4364 std::list<NotifyArgs> processPressure(SingleTouchInputMapper& mapper, int32_t pressure);
4365 std::list<NotifyArgs> processToolMajor(SingleTouchInputMapper& mapper, int32_t toolMajor);
4366 std::list<NotifyArgs> processDistance(SingleTouchInputMapper& mapper, int32_t distance);
4367 std::list<NotifyArgs> processTilt(SingleTouchInputMapper& mapper, int32_t tiltX, int32_t tiltY);
4368 std::list<NotifyArgs> processKey(SingleTouchInputMapper& mapper, int32_t code, int32_t value);
4369 std::list<NotifyArgs> processSync(SingleTouchInputMapper& mapper);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004370};
4371
4372void SingleTouchInputMapperTest::prepareButtons() {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004373 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004374}
4375
4376void SingleTouchInputMapperTest::prepareAxes(int axes) {
4377 if (axes & POSITION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004378 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
4379 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004380 }
4381 if (axes & PRESSURE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004382 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_PRESSURE, RAW_PRESSURE_MIN,
4383 RAW_PRESSURE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004384 }
4385 if (axes & TOOL) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004386 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TOOL_WIDTH, RAW_TOOL_MIN, RAW_TOOL_MAX, 0,
4387 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004388 }
4389 if (axes & DISTANCE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004390 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_DISTANCE, RAW_DISTANCE_MIN,
4391 RAW_DISTANCE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004392 }
4393 if (axes & TILT) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08004394 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TILT_X, RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
4395 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TILT_Y, RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004396 }
4397}
4398
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004399std::list<NotifyArgs> SingleTouchInputMapperTest::processDown(SingleTouchInputMapper& mapper,
4400 int32_t x, int32_t y) {
4401 std::list<NotifyArgs> args;
4402 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
4403 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, x);
4404 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, y);
4405 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004406}
4407
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004408std::list<NotifyArgs> SingleTouchInputMapperTest::processMove(SingleTouchInputMapper& mapper,
4409 int32_t x, int32_t y) {
4410 std::list<NotifyArgs> args;
4411 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, x);
4412 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, y);
4413 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004414}
4415
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004416std::list<NotifyArgs> SingleTouchInputMapperTest::processUp(SingleTouchInputMapper& mapper) {
4417 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004418}
4419
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004420std::list<NotifyArgs> SingleTouchInputMapperTest::processPressure(SingleTouchInputMapper& mapper,
4421 int32_t pressure) {
4422 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_PRESSURE, pressure);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004423}
4424
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004425std::list<NotifyArgs> SingleTouchInputMapperTest::processToolMajor(SingleTouchInputMapper& mapper,
4426 int32_t toolMajor) {
4427 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TOOL_WIDTH, toolMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004428}
4429
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004430std::list<NotifyArgs> SingleTouchInputMapperTest::processDistance(SingleTouchInputMapper& mapper,
4431 int32_t distance) {
4432 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_DISTANCE, distance);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004433}
4434
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004435std::list<NotifyArgs> SingleTouchInputMapperTest::processTilt(SingleTouchInputMapper& mapper,
4436 int32_t tiltX, int32_t tiltY) {
4437 std::list<NotifyArgs> args;
4438 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TILT_X, tiltX);
4439 args += process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_TILT_Y, tiltY);
4440 return args;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004441}
4442
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004443std::list<NotifyArgs> SingleTouchInputMapperTest::processKey(SingleTouchInputMapper& mapper,
4444 int32_t code, int32_t value) {
4445 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004446}
4447
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004448std::list<NotifyArgs> SingleTouchInputMapperTest::processSync(SingleTouchInputMapper& mapper) {
4449 return process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004450}
4451
Michael Wrightd02c5b62014-02-10 15:10:22 -08004452TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndNotACursor_ReturnsPointer) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004453 prepareButtons();
4454 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00004455 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004456
Josep del Río2d8c79a2023-01-23 19:33:50 +00004457 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004458}
4459
Michael Wrightd02c5b62014-02-10 15:10:22 -08004460TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004461 prepareButtons();
4462 prepareAxes(POSITION);
4463 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00004464 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004465
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004466 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004467}
4468
4469TEST_F(SingleTouchInputMapperTest, GetKeyCodeState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004470 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004471 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004472 prepareButtons();
4473 prepareAxes(POSITION);
4474 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004475 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004476
4477 // Unknown key.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004478 ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004479
4480 // Virtual key is down.
4481 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4482 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4483 processDown(mapper, x, y);
4484 processSync(mapper);
4485 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4486
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004487 ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004488
4489 // Virtual key is up.
4490 processUp(mapper);
4491 processSync(mapper);
4492 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4493
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004494 ASSERT_EQ(AKEY_STATE_UP, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004495}
4496
4497TEST_F(SingleTouchInputMapperTest, GetScanCodeState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004498 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004499 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004500 prepareButtons();
4501 prepareAxes(POSITION);
4502 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004503 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004504
4505 // Unknown key.
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004506 ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004507
4508 // Virtual key is down.
4509 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4510 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4511 processDown(mapper, x, y);
4512 processSync(mapper);
4513 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4514
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004515 ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004516
4517 // Virtual key is up.
4518 processUp(mapper);
4519 processSync(mapper);
4520 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
4521
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08004522 ASSERT_EQ(AKEY_STATE_UP, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004523}
4524
4525TEST_F(SingleTouchInputMapperTest, MarkSupportedKeyCodes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004526 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004527 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004528 prepareButtons();
4529 prepareAxes(POSITION);
4530 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004531 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004532
Michael Wrightd02c5b62014-02-10 15:10:22 -08004533 uint8_t flags[2] = { 0, 0 };
Siarhei Vishniakou74007942022-06-13 13:57:47 -07004534 ASSERT_TRUE(
4535 mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_HOME, AKEYCODE_A}, flags));
Michael Wrightd02c5b62014-02-10 15:10:22 -08004536 ASSERT_TRUE(flags[0]);
4537 ASSERT_FALSE(flags[1]);
4538}
4539
Biswarup Pal9ce4d9f2024-06-14 15:05:27 +00004540TEST_F(SingleTouchInputMapperTest, DeviceTypeChange_RecalculatesRawToDisplayTransform) {
4541 prepareDisplay(ui::ROTATION_0);
4542 prepareAxes(POSITION);
4543 addConfigurationProperty("touch.deviceType", "touchScreen");
4544 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
4545
4546 const int32_t x = 900;
4547 const int32_t y = 75;
4548 std::list<NotifyArgs> args;
4549 args += processDown(mapper, x, y);
4550 args += processSync(mapper);
4551
4552 // Assert that motion event is received in display coordinate space for deviceType touchScreen.
4553 ASSERT_THAT(args,
4554 ElementsAre(VariantWith<NotifyMotionArgs>(
4555 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4556 WithCoords(toDisplayX(x), toDisplayY(y))))));
4557
4558 // Add device type association after the device was created.
4559 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
4560 // Send update to the mapper.
4561 std::list<NotifyArgs> unused =
4562 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
4563 InputReaderConfiguration::Change::DEVICE_TYPE /*changes*/);
4564
4565 args.clear();
4566 args += processDown(mapper, x, y);
4567 args += processSync(mapper);
4568
4569 // Assert that motion event is received in raw coordinate space for deviceType touchNavigation.
4570 ASSERT_THAT(args,
4571 ElementsAre(VariantWith<NotifyMotionArgs>(
4572 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4573 WithCoords(x - RAW_X_MIN, y - RAW_Y_MIN)))));
4574}
4575
Michael Wrightd02c5b62014-02-10 15:10:22 -08004576TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNormally_SendsKeyDownAndKeyUp) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004577 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004578 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004579 prepareButtons();
4580 prepareAxes(POSITION);
4581 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004582 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004583
arthurhungdcef2dc2020-08-11 14:47:50 +08004584 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004585
4586 NotifyKeyArgs args;
4587
4588 // Press virtual key.
4589 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4590 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4591 processDown(mapper, x, y);
4592 processSync(mapper);
4593
4594 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4595 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4596 ASSERT_EQ(DEVICE_ID, args.deviceId);
4597 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4598 ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
4599 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
4600 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
4601 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4602 ASSERT_EQ(KEY_HOME, args.scanCode);
4603 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
4604 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
4605
4606 // Release virtual key.
4607 processUp(mapper);
4608 processSync(mapper);
4609
4610 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
4611 ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
4612 ASSERT_EQ(DEVICE_ID, args.deviceId);
4613 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
4614 ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
4615 ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
4616 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
4617 ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
4618 ASSERT_EQ(KEY_HOME, args.scanCode);
4619 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
4620 ASSERT_EQ(ARBITRARY_TIME, args.downTime);
4621
4622 // Should not have sent any motions.
4623 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4624}
4625
4626TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfBounds_SendsKeyDownAndKeyCancel) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004627 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004628 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004629 prepareButtons();
4630 prepareAxes(POSITION);
4631 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004632 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004633
arthurhungdcef2dc2020-08-11 14:47:50 +08004634 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004635
4636 NotifyKeyArgs keyArgs;
4637
4638 // Press virtual key.
4639 int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
4640 int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
4641 processDown(mapper, x, y);
4642 processSync(mapper);
4643
4644 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
4645 ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
4646 ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
4647 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
4648 ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
4649 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
4650 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, keyArgs.flags);
4651 ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
4652 ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
4653 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
4654 ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
4655
4656 // Move out of bounds. This should generate a cancel and a pointer down since we moved
4657 // into the display area.
4658 y -= 100;
4659 processMove(mapper, x, y);
4660 processSync(mapper);
4661
4662 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
4663 ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
4664 ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
4665 ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
4666 ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
4667 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
4668 ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
4669 | AKEY_EVENT_FLAG_CANCELED, keyArgs.flags);
4670 ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
4671 ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
4672 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
4673 ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
4674
4675 NotifyMotionArgs motionArgs;
4676 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4677 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4678 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4679 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4680 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4681 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4682 ASSERT_EQ(0, motionArgs.flags);
4683 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4684 ASSERT_EQ(0, motionArgs.buttonState);
4685 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004686 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004687 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004688 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004689 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4690 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4691 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4692 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4693 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4694
4695 // Keep moving out of bounds. Should generate a pointer move.
4696 y -= 50;
4697 processMove(mapper, x, y);
4698 processSync(mapper);
4699
4700 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4701 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4702 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4703 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4704 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4705 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
4706 ASSERT_EQ(0, motionArgs.flags);
4707 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4708 ASSERT_EQ(0, motionArgs.buttonState);
4709 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004710 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004711 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004712 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004713 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4714 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4715 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4716 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4717 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4718
4719 // Release out of bounds. Should generate a pointer up.
4720 processUp(mapper);
4721 processSync(mapper);
4722
4723 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4724 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4725 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4726 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4727 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4728 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4729 ASSERT_EQ(0, motionArgs.flags);
4730 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4731 ASSERT_EQ(0, motionArgs.buttonState);
4732 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004733 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004734 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004735 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004736 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4737 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4738 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4739 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4740 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4741
4742 // Should not have sent any more keys or motions.
4743 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4744 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4745}
4746
4747TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMovesIn_SendsDownAsTouchEntersDisplay) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004748 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004749 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004750 prepareButtons();
4751 prepareAxes(POSITION);
4752 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004753 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004754
arthurhungdcef2dc2020-08-11 14:47:50 +08004755 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004756
4757 NotifyMotionArgs motionArgs;
4758
4759 // Initially go down out of bounds.
4760 int32_t x = -10;
4761 int32_t y = -10;
4762 processDown(mapper, x, y);
4763 processSync(mapper);
4764
4765 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4766
4767 // Move into the display area. Should generate a pointer down.
4768 x = 50;
4769 y = 75;
4770 processMove(mapper, x, y);
4771 processSync(mapper);
4772
4773 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4774 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4775 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4776 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4777 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4778 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4779 ASSERT_EQ(0, motionArgs.flags);
4780 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4781 ASSERT_EQ(0, motionArgs.buttonState);
4782 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004783 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004784 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004785 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004786 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4787 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4788 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4789 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4790 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4791
4792 // Release. Should generate a pointer up.
4793 processUp(mapper);
4794 processSync(mapper);
4795
4796 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4797 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4798 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4799 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4800 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4801 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4802 ASSERT_EQ(0, motionArgs.flags);
4803 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4804 ASSERT_EQ(0, motionArgs.buttonState);
4805 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004806 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004807 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004808 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004809 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4810 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4811 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4812 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4813 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4814
4815 // Should not have sent any more keys or motions.
4816 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4817 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4818}
4819
Santos Cordonfa5cf462017-04-05 10:37:00 -07004820TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture_VirtualDisplay) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07004821 addConfigurationProperty("touch.deviceType", "touchScreen");
4822 addConfigurationProperty("touch.displayId", VIRTUAL_DISPLAY_UNIQUE_ID);
4823
Michael Wrighta9cf4192022-12-01 23:46:39 +00004824 prepareVirtualDisplay(ui::ROTATION_0);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004825 prepareButtons();
4826 prepareAxes(POSITION);
4827 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004828 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Santos Cordonfa5cf462017-04-05 10:37:00 -07004829
arthurhungdcef2dc2020-08-11 14:47:50 +08004830 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004831
4832 NotifyMotionArgs motionArgs;
4833
4834 // Down.
4835 int32_t x = 100;
4836 int32_t y = 125;
4837 processDown(mapper, x, y);
4838 processSync(mapper);
4839
4840 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4841 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4842 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4843 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4844 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4845 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4846 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4847 ASSERT_EQ(0, motionArgs.flags);
4848 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4849 ASSERT_EQ(0, motionArgs.buttonState);
4850 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004851 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004852 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004853 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004854 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4855 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4856 1, 0, 0, 0, 0, 0, 0, 0));
4857 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4858 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4859 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4860
4861 // Move.
4862 x += 50;
4863 y += 75;
4864 processMove(mapper, x, y);
4865 processSync(mapper);
4866
4867 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4868 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4869 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4870 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4871 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4872 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4873 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
4874 ASSERT_EQ(0, motionArgs.flags);
4875 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4876 ASSERT_EQ(0, motionArgs.buttonState);
4877 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004878 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004879 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004880 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004881 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4882 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4883 1, 0, 0, 0, 0, 0, 0, 0));
4884 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4885 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4886 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4887
4888 // Up.
4889 processUp(mapper);
4890 processSync(mapper);
4891
4892 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4893 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4894 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4895 ASSERT_EQ(VIRTUAL_DISPLAY_ID, motionArgs.displayId);
4896 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4897 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4898 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4899 ASSERT_EQ(0, motionArgs.flags);
4900 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4901 ASSERT_EQ(0, motionArgs.buttonState);
4902 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004903 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Santos Cordonfa5cf462017-04-05 10:37:00 -07004904 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004905 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Santos Cordonfa5cf462017-04-05 10:37:00 -07004906 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4907 toDisplayX(x, VIRTUAL_DISPLAY_WIDTH), toDisplayY(y, VIRTUAL_DISPLAY_HEIGHT),
4908 1, 0, 0, 0, 0, 0, 0, 0));
4909 ASSERT_NEAR(X_PRECISION_VIRTUAL, motionArgs.xPrecision, EPSILON);
4910 ASSERT_NEAR(Y_PRECISION_VIRTUAL, motionArgs.yPrecision, EPSILON);
4911 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4912
4913 // Should not have sent any more keys or motions.
4914 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
4915 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
4916}
4917
Michael Wrightd02c5b62014-02-10 15:10:22 -08004918TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004919 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00004920 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004921 prepareButtons();
4922 prepareAxes(POSITION);
4923 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00004924 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004925
arthurhungdcef2dc2020-08-11 14:47:50 +08004926 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004927
4928 NotifyMotionArgs motionArgs;
4929
4930 // Down.
4931 int32_t x = 100;
4932 int32_t y = 125;
4933 processDown(mapper, x, y);
4934 processSync(mapper);
4935
4936 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4937 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4938 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4939 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4940 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4941 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
4942 ASSERT_EQ(0, motionArgs.flags);
4943 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4944 ASSERT_EQ(0, motionArgs.buttonState);
4945 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004946 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004947 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004948 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004949 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4950 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4951 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4952 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4953 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4954
4955 // Move.
4956 x += 50;
4957 y += 75;
4958 processMove(mapper, x, y);
4959 processSync(mapper);
4960
4961 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4962 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4963 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4964 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4965 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4966 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
4967 ASSERT_EQ(0, motionArgs.flags);
4968 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4969 ASSERT_EQ(0, motionArgs.buttonState);
4970 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004971 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004972 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004973 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004974 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4975 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4976 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
4977 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
4978 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
4979
4980 // Up.
4981 processUp(mapper);
4982 processSync(mapper);
4983
4984 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
4985 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
4986 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
4987 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
4988 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
4989 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
4990 ASSERT_EQ(0, motionArgs.flags);
4991 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
4992 ASSERT_EQ(0, motionArgs.buttonState);
4993 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07004994 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08004995 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004996 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004997 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
4998 toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
4999 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
5000 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
5001 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
5002
5003 // Should not have sent any more keys or motions.
5004 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5005 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5006}
5007
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005008TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_DoesNotRotateMotions) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005009 addConfigurationProperty("touch.deviceType", "touchScreen");
5010 prepareButtons();
5011 prepareAxes(POSITION);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005012 // InputReader works in the un-rotated coordinate space, so orientation-aware devices do not
5013 // need to be rotated. Touchscreens are orientation-aware by default.
Arpit Singha8c236b2023-04-25 13:56:05 +00005014 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005015
5016 NotifyMotionArgs args;
5017
5018 // Rotation 90.
Michael Wrighta9cf4192022-12-01 23:46:39 +00005019 prepareDisplay(ui::ROTATION_90);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005020 processDown(mapper, toRawX(50), toRawY(75));
5021 processSync(mapper);
5022
5023 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5024 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5025 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5026
5027 processUp(mapper);
5028 processSync(mapper);
5029 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5030}
5031
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005032TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_RotatesMotions) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005033 addConfigurationProperty("touch.deviceType", "touchScreen");
5034 prepareButtons();
5035 prepareAxes(POSITION);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07005036 // Since InputReader works in the un-rotated coordinate space, only devices that are not
5037 // orientation-aware are affected by display rotation.
5038 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00005039 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005040
5041 NotifyMotionArgs args;
5042
5043 // Rotation 0.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005044 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005045 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005046 processDown(mapper, toRawX(50), toRawY(75));
5047 processSync(mapper);
5048
5049 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5050 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5051 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5052
5053 processUp(mapper);
5054 processSync(mapper);
5055 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5056
5057 // Rotation 90.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005058 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005059 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005060 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005061 processSync(mapper);
5062
5063 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5064 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5065 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5066
5067 processUp(mapper);
5068 processSync(mapper);
5069 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5070
5071 // Rotation 180.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005072 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005073 prepareDisplay(ui::ROTATION_180);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005074 processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
5075 processSync(mapper);
5076
5077 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5078 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5079 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5080
5081 processUp(mapper);
5082 processSync(mapper);
5083 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5084
5085 // Rotation 270.
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07005086 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005087 prepareDisplay(ui::ROTATION_270);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005088 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005089 processSync(mapper);
5090
5091 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5092 ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5093 ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5094
5095 processUp(mapper);
5096 processSync(mapper);
5097 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5098}
5099
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005100TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation0_RotatesMotions) {
5101 addConfigurationProperty("touch.deviceType", "touchScreen");
5102 prepareButtons();
5103 prepareAxes(POSITION);
5104 addConfigurationProperty("touch.orientationAware", "1");
5105 addConfigurationProperty("touch.orientation", "ORIENTATION_0");
5106 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005107 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005108 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005109 NotifyMotionArgs args;
5110
5111 // Orientation 0.
5112 processDown(mapper, toRawX(50), toRawY(75));
5113 processSync(mapper);
5114
5115 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5116 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5117 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5118
5119 processUp(mapper);
5120 processSync(mapper);
5121 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5122}
5123
5124TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation90_RotatesMotions) {
5125 addConfigurationProperty("touch.deviceType", "touchScreen");
5126 prepareButtons();
5127 prepareAxes(POSITION);
5128 addConfigurationProperty("touch.orientationAware", "1");
5129 addConfigurationProperty("touch.orientation", "ORIENTATION_90");
5130 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005131 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005132 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005133 NotifyMotionArgs args;
5134
5135 // Orientation 90.
5136 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
5137 processSync(mapper);
5138
5139 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5140 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5141 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5142
5143 processUp(mapper);
5144 processSync(mapper);
5145 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5146}
5147
5148TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation180_RotatesMotions) {
5149 addConfigurationProperty("touch.deviceType", "touchScreen");
5150 prepareButtons();
5151 prepareAxes(POSITION);
5152 addConfigurationProperty("touch.orientationAware", "1");
5153 addConfigurationProperty("touch.orientation", "ORIENTATION_180");
5154 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005155 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005156 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005157 NotifyMotionArgs args;
5158
5159 // Orientation 180.
5160 processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
5161 processSync(mapper);
5162
5163 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5164 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5165 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5166
5167 processUp(mapper);
5168 processSync(mapper);
5169 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5170}
5171
5172TEST_F(SingleTouchInputMapperTest, Process_WhenOrientation270_RotatesMotions) {
5173 addConfigurationProperty("touch.deviceType", "touchScreen");
5174 prepareButtons();
5175 prepareAxes(POSITION);
5176 addConfigurationProperty("touch.orientationAware", "1");
5177 addConfigurationProperty("touch.orientation", "ORIENTATION_270");
5178 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005179 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005180 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005181 NotifyMotionArgs args;
5182
5183 // Orientation 270.
5184 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
5185 processSync(mapper);
5186
5187 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5188 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5189 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5190
5191 processUp(mapper);
5192 processSync(mapper);
5193 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5194}
5195
5196TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationSpecified_RotatesMotionWithDisplay) {
5197 addConfigurationProperty("touch.deviceType", "touchScreen");
5198 prepareButtons();
5199 prepareAxes(POSITION);
5200 // Since InputReader works in the un-rotated coordinate space, only devices that are not
5201 // orientation-aware are affected by display rotation.
5202 addConfigurationProperty("touch.orientationAware", "0");
5203 addConfigurationProperty("touch.orientation", "ORIENTATION_90");
Arpit Singha8c236b2023-04-25 13:56:05 +00005204 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005205
5206 NotifyMotionArgs args;
5207
5208 // Orientation 90, Rotation 0.
5209 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005210 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005211 processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
5212 processSync(mapper);
5213
5214 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5215 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5216 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5217
5218 processUp(mapper);
5219 processSync(mapper);
5220 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5221
5222 // Orientation 90, Rotation 90.
5223 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005224 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005225 processDown(mapper, toRawX(50), toRawY(75));
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005226 processSync(mapper);
5227
5228 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5229 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5230 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5231
5232 processUp(mapper);
5233 processSync(mapper);
5234 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5235
5236 // Orientation 90, Rotation 180.
5237 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005238 prepareDisplay(ui::ROTATION_180);
Prabir Pradhanac1c74f2021-08-20 16:09:32 -07005239 processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
5240 processSync(mapper);
5241
5242 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5243 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5244 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5245
5246 processUp(mapper);
5247 processSync(mapper);
5248 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5249
5250 // Orientation 90, Rotation 270.
5251 clearViewports();
Michael Wrighta9cf4192022-12-01 23:46:39 +00005252 prepareDisplay(ui::ROTATION_270);
Prabir Pradhanea31d4f2022-11-10 20:48:01 +00005253 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 -07005254 processSync(mapper);
5255
5256 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5257 EXPECT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5258 EXPECT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5259
5260 processUp(mapper);
5261 processSync(mapper);
5262 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5263}
5264
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005265TEST_F(SingleTouchInputMapperTest, Process_IgnoresTouchesOutsidePhysicalFrame) {
5266 addConfigurationProperty("touch.deviceType", "touchScreen");
5267 prepareButtons();
5268 prepareAxes(POSITION);
5269 addConfigurationProperty("touch.orientationAware", "1");
5270 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005271 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005272
5273 // Set a physical frame in the display viewport.
5274 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
5275 viewport->physicalLeft = 20;
5276 viewport->physicalTop = 600;
5277 viewport->physicalRight = 30;
5278 viewport->physicalBottom = 610;
5279 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00005280 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhan675f25a2022-11-10 22:04:07 +00005281
5282 // Start the touch.
5283 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
5284 processSync(mapper);
5285
5286 // Expect all input starting outside the physical frame to be ignored.
5287 const std::array<Point, 6> outsidePoints = {
5288 {{0, 0}, {19, 605}, {31, 605}, {25, 599}, {25, 611}, {DISPLAY_WIDTH, DISPLAY_HEIGHT}}};
5289 for (const auto& p : outsidePoints) {
5290 processMove(mapper, toRawX(p.x), toRawY(p.y));
5291 processSync(mapper);
5292 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5293 }
5294
5295 // Move the touch into the physical frame.
5296 processMove(mapper, toRawX(25), toRawY(605));
5297 processSync(mapper);
5298 NotifyMotionArgs args;
5299 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5300 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
5301 EXPECT_NEAR(25, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5302 EXPECT_NEAR(605, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5303
5304 // Once the touch down is reported, continue reporting input, even if it is outside the frame.
5305 for (const auto& p : outsidePoints) {
5306 processMove(mapper, toRawX(p.x), toRawY(p.y));
5307 processSync(mapper);
5308 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5309 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
5310 EXPECT_NEAR(p.x, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
5311 EXPECT_NEAR(p.y, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
5312 }
5313
5314 processUp(mapper);
5315 processSync(mapper);
5316 EXPECT_NO_FATAL_FAILURE(
5317 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
5318}
5319
Harry Cutts1db43992023-06-19 17:05:07 +00005320TEST_F(SingleTouchInputMapperTest, Process_DoesntCheckPhysicalFrameForTouchpads) {
Harry Cutts1db43992023-06-19 17:05:07 +00005321 addConfigurationProperty("touch.deviceType", "pointer");
5322 prepareAxes(POSITION);
5323 prepareDisplay(ui::ROTATION_0);
5324 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
5325
5326 // Set a physical frame in the display viewport.
5327 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
5328 viewport->physicalLeft = 20;
5329 viewport->physicalTop = 600;
5330 viewport->physicalRight = 30;
5331 viewport->physicalBottom = 610;
5332 mFakePolicy->updateViewport(*viewport);
5333 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
5334
5335 // Start the touch.
5336 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, BTN_TOUCH, 1);
5337 processSync(mapper);
5338
5339 // Expect all input starting outside the physical frame to result in NotifyMotionArgs being
5340 // produced.
5341 const std::array<Point, 6> outsidePoints = {
5342 {{0, 0}, {19, 605}, {31, 605}, {25, 599}, {25, 611}, {DISPLAY_WIDTH, DISPLAY_HEIGHT}}};
5343 for (const auto& p : outsidePoints) {
5344 processMove(mapper, toRawX(p.x), toRawY(p.y));
5345 processSync(mapper);
5346 EXPECT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
5347 }
5348}
5349
Michael Wrightd02c5b62014-02-10 15:10:22 -08005350TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005351 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005352 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005353 prepareButtons();
5354 prepareAxes(POSITION | PRESSURE | TOOL | DISTANCE | TILT);
Arpit Singha8c236b2023-04-25 13:56:05 +00005355 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005356
5357 // These calculations are based on the input device calibration documentation.
5358 int32_t rawX = 100;
5359 int32_t rawY = 200;
5360 int32_t rawPressure = 10;
5361 int32_t rawToolMajor = 12;
5362 int32_t rawDistance = 2;
5363 int32_t rawTiltX = 30;
5364 int32_t rawTiltY = 110;
5365
5366 float x = toDisplayX(rawX);
5367 float y = toDisplayY(rawY);
5368 float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
5369 float size = float(rawToolMajor) / RAW_TOOL_MAX;
5370 float tool = float(rawToolMajor) * GEOMETRIC_SCALE;
5371 float distance = float(rawDistance);
5372
5373 float tiltCenter = (RAW_TILT_MAX + RAW_TILT_MIN) * 0.5f;
5374 float tiltScale = M_PI / 180;
5375 float tiltXAngle = (rawTiltX - tiltCenter) * tiltScale;
5376 float tiltYAngle = (rawTiltY - tiltCenter) * tiltScale;
5377 float orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
5378 float tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
5379
5380 processDown(mapper, rawX, rawY);
5381 processPressure(mapper, rawPressure);
5382 processToolMajor(mapper, rawToolMajor);
5383 processDistance(mapper, rawDistance);
5384 processTilt(mapper, rawTiltX, rawTiltY);
5385 processSync(mapper);
5386
5387 NotifyMotionArgs args;
5388 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5389 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
5390 x, y, pressure, size, tool, tool, tool, tool, orientation, distance));
5391 ASSERT_EQ(tilt, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TILT));
Prabir Pradhan9a53b552024-06-04 02:59:40 +00005392 ASSERT_EQ(args.flags,
5393 AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION |
5394 AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005395}
5396
Jason Gerecke489fda82012-09-07 17:19:40 -07005397TEST_F(SingleTouchInputMapperTest, Process_XYAxes_AffineCalibration) {
Jason Gerecke489fda82012-09-07 17:19:40 -07005398 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005399 prepareDisplay(ui::ROTATION_0);
Jason Gerecke489fda82012-09-07 17:19:40 -07005400 prepareLocationCalibration();
5401 prepareButtons();
5402 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005403 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Jason Gerecke489fda82012-09-07 17:19:40 -07005404
5405 int32_t rawX = 100;
5406 int32_t rawY = 200;
5407
5408 float x = toDisplayX(toCookedX(rawX, rawY));
5409 float y = toDisplayY(toCookedY(rawX, rawY));
5410
5411 processDown(mapper, rawX, rawY);
5412 processSync(mapper);
5413
5414 NotifyMotionArgs args;
5415 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
5416 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
5417 x, y, 1, 0, 0, 0, 0, 0, 0, 0));
5418}
5419
Michael Wrightd02c5b62014-02-10 15:10:22 -08005420TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllButtons) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005421 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005422 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005423 prepareButtons();
5424 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005425 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005426
5427 NotifyMotionArgs motionArgs;
5428 NotifyKeyArgs keyArgs;
5429
5430 processDown(mapper, 100, 200);
5431 processSync(mapper);
5432 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5433 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5434 ASSERT_EQ(0, motionArgs.buttonState);
5435
5436 // press BTN_LEFT, release BTN_LEFT
5437 processKey(mapper, BTN_LEFT, 1);
5438 processSync(mapper);
5439 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5440 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5441 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
5442
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005443 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5444 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5445 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
5446
Michael Wrightd02c5b62014-02-10 15:10:22 -08005447 processKey(mapper, BTN_LEFT, 0);
5448 processSync(mapper);
5449 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005450 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005451 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005452
5453 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005454 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005455 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005456
5457 // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
5458 processKey(mapper, BTN_RIGHT, 1);
5459 processKey(mapper, BTN_MIDDLE, 1);
5460 processSync(mapper);
5461 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5462 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
5463 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
5464 motionArgs.buttonState);
5465
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005466 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5467 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5468 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
5469
5470 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5471 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5472 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
5473 motionArgs.buttonState);
5474
Michael Wrightd02c5b62014-02-10 15:10:22 -08005475 processKey(mapper, BTN_RIGHT, 0);
5476 processSync(mapper);
5477 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005478 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005479 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005480
5481 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005482 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005483 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005484
5485 processKey(mapper, BTN_MIDDLE, 0);
5486 processSync(mapper);
5487 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005488 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005489 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005490
5491 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005492 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005493 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005494
5495 // press BTN_BACK, release BTN_BACK
5496 processKey(mapper, BTN_BACK, 1);
5497 processSync(mapper);
5498 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5499 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5500 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005501
Michael Wrightd02c5b62014-02-10 15:10:22 -08005502 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005503 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005504 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
5505
5506 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5507 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5508 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005509
5510 processKey(mapper, BTN_BACK, 0);
5511 processSync(mapper);
5512 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005513 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005514 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005515
5516 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005517 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005518 ASSERT_EQ(0, motionArgs.buttonState);
5519
Michael Wrightd02c5b62014-02-10 15:10:22 -08005520 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5521 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5522 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
5523
5524 // press BTN_SIDE, release BTN_SIDE
5525 processKey(mapper, BTN_SIDE, 1);
5526 processSync(mapper);
5527 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5528 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5529 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005530
Michael Wrightd02c5b62014-02-10 15:10:22 -08005531 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005532 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005533 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
5534
5535 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5536 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5537 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005538
5539 processKey(mapper, BTN_SIDE, 0);
5540 processSync(mapper);
5541 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005542 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005543 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005544
5545 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005546 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005547 ASSERT_EQ(0, motionArgs.buttonState);
5548
Michael Wrightd02c5b62014-02-10 15:10:22 -08005549 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5550 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5551 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
5552
5553 // press BTN_FORWARD, release BTN_FORWARD
5554 processKey(mapper, BTN_FORWARD, 1);
5555 processSync(mapper);
5556 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5557 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5558 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005559
Michael Wrightd02c5b62014-02-10 15:10:22 -08005560 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005561 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005562 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
5563
5564 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5565 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5566 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005567
5568 processKey(mapper, BTN_FORWARD, 0);
5569 processSync(mapper);
5570 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005571 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005572 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005573
5574 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005575 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005576 ASSERT_EQ(0, motionArgs.buttonState);
5577
Michael Wrightd02c5b62014-02-10 15:10:22 -08005578 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5579 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5580 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
5581
5582 // press BTN_EXTRA, release BTN_EXTRA
5583 processKey(mapper, BTN_EXTRA, 1);
5584 processSync(mapper);
5585 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5586 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
5587 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005588
Michael Wrightd02c5b62014-02-10 15:10:22 -08005589 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005590 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005591 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
5592
5593 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5594 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5595 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005596
5597 processKey(mapper, BTN_EXTRA, 0);
5598 processSync(mapper);
5599 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005600 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005601 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005602
5603 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005604 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005605 ASSERT_EQ(0, motionArgs.buttonState);
5606
Michael Wrightd02c5b62014-02-10 15:10:22 -08005607 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
5608 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
5609 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
5610
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005611 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
5612
Michael Wrightd02c5b62014-02-10 15:10:22 -08005613 // press BTN_STYLUS, release BTN_STYLUS
5614 processKey(mapper, BTN_STYLUS, 1);
5615 processSync(mapper);
5616 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5617 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005618 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
5619
5620 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5621 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5622 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005623
5624 processKey(mapper, BTN_STYLUS, 0);
5625 processSync(mapper);
5626 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005627 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005628 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005629
5630 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005631 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005632 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005633
5634 // press BTN_STYLUS2, release BTN_STYLUS2
5635 processKey(mapper, BTN_STYLUS2, 1);
5636 processSync(mapper);
5637 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5638 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005639 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
5640
5641 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5642 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
5643 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005644
5645 processKey(mapper, BTN_STYLUS2, 0);
5646 processSync(mapper);
5647 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005648 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005649 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005650
5651 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08005652 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08005653 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005654
5655 // release touch
5656 processUp(mapper);
5657 processSync(mapper);
5658 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5659 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5660 ASSERT_EQ(0, motionArgs.buttonState);
5661}
5662
5663TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005664 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005665 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005666 prepareButtons();
5667 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005668 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005669
5670 NotifyMotionArgs motionArgs;
5671
5672 // default tool type is finger
5673 processDown(mapper, 100, 200);
5674 processSync(mapper);
5675 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5676 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005677 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005678
5679 // eraser
5680 processKey(mapper, BTN_TOOL_RUBBER, 1);
5681 processSync(mapper);
5682 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5683 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005684 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005685
5686 // stylus
5687 processKey(mapper, BTN_TOOL_RUBBER, 0);
5688 processKey(mapper, BTN_TOOL_PEN, 1);
5689 processSync(mapper);
5690 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5691 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005692 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005693
5694 // brush
5695 processKey(mapper, BTN_TOOL_PEN, 0);
5696 processKey(mapper, BTN_TOOL_BRUSH, 1);
5697 processSync(mapper);
5698 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5699 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005700 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005701
5702 // pencil
5703 processKey(mapper, BTN_TOOL_BRUSH, 0);
5704 processKey(mapper, BTN_TOOL_PENCIL, 1);
5705 processSync(mapper);
5706 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5707 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005708 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005709
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08005710 // air-brush
Michael Wrightd02c5b62014-02-10 15:10:22 -08005711 processKey(mapper, BTN_TOOL_PENCIL, 0);
5712 processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
5713 processSync(mapper);
5714 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5715 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005716 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005717
5718 // mouse
5719 processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
5720 processKey(mapper, BTN_TOOL_MOUSE, 1);
5721 processSync(mapper);
5722 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5723 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005724 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005725
5726 // lens
5727 processKey(mapper, BTN_TOOL_MOUSE, 0);
5728 processKey(mapper, BTN_TOOL_LENS, 1);
5729 processSync(mapper);
5730 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5731 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005732 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005733
5734 // double-tap
5735 processKey(mapper, BTN_TOOL_LENS, 0);
5736 processKey(mapper, BTN_TOOL_DOUBLETAP, 1);
5737 processSync(mapper);
5738 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5739 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005740 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005741
5742 // triple-tap
5743 processKey(mapper, BTN_TOOL_DOUBLETAP, 0);
5744 processKey(mapper, BTN_TOOL_TRIPLETAP, 1);
5745 processSync(mapper);
5746 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5747 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005748 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005749
5750 // quad-tap
5751 processKey(mapper, BTN_TOOL_TRIPLETAP, 0);
5752 processKey(mapper, BTN_TOOL_QUADTAP, 1);
5753 processSync(mapper);
5754 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5755 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005756 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005757
5758 // finger
5759 processKey(mapper, BTN_TOOL_QUADTAP, 0);
5760 processKey(mapper, BTN_TOOL_FINGER, 1);
5761 processSync(mapper);
5762 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5763 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005764 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005765
5766 // stylus trumps finger
5767 processKey(mapper, BTN_TOOL_PEN, 1);
5768 processSync(mapper);
5769 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5770 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005771 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005772
5773 // eraser trumps stylus
5774 processKey(mapper, BTN_TOOL_RUBBER, 1);
5775 processSync(mapper);
5776 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5777 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005778 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005779
5780 // mouse trumps eraser
5781 processKey(mapper, BTN_TOOL_MOUSE, 1);
5782 processSync(mapper);
5783 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5784 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005785 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005786
5787 // back to default tool type
5788 processKey(mapper, BTN_TOOL_MOUSE, 0);
5789 processKey(mapper, BTN_TOOL_RUBBER, 0);
5790 processKey(mapper, BTN_TOOL_PEN, 0);
5791 processKey(mapper, BTN_TOOL_FINGER, 0);
5792 processSync(mapper);
5793 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5794 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005795 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005796}
5797
5798TEST_F(SingleTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005799 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005800 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005801 prepareButtons();
5802 prepareAxes(POSITION);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08005803 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_FINGER, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00005804 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005805
5806 NotifyMotionArgs motionArgs;
5807
5808 // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0
5809 processKey(mapper, BTN_TOOL_FINGER, 1);
5810 processMove(mapper, 100, 200);
5811 processSync(mapper);
5812 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5813 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5814 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5815 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5816
5817 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5818 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5819 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5820 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5821
5822 // move a little
5823 processMove(mapper, 150, 250);
5824 processSync(mapper);
5825 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5826 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5827 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5828 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5829
5830 // down when BTN_TOUCH is pressed, pressure defaults to 1
5831 processKey(mapper, BTN_TOUCH, 1);
5832 processSync(mapper);
5833 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5834 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5835 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5836 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5837
5838 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5839 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5840 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5841 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5842
5843 // up when BTN_TOUCH is released, hover restored
5844 processKey(mapper, BTN_TOUCH, 0);
5845 processSync(mapper);
5846 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5847 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5848 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5849 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5850
5851 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5852 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5853 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5854 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5855
5856 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5857 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5858 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5859 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5860
5861 // exit hover when pointer goes away
5862 processKey(mapper, BTN_TOOL_FINGER, 0);
5863 processSync(mapper);
5864 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5865 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5866 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5867 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5868}
5869
5870TEST_F(SingleTouchInputMapperTest, Process_WhenAbsPressureIsPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005871 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005872 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005873 prepareButtons();
5874 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00005875 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005876
5877 NotifyMotionArgs motionArgs;
5878
5879 // initially hovering because pressure is 0
5880 processDown(mapper, 100, 200);
5881 processPressure(mapper, 0);
5882 processSync(mapper);
5883 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5884 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5885 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5886 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5887
5888 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5889 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5890 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5891 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
5892
5893 // move a little
5894 processMove(mapper, 150, 250);
5895 processSync(mapper);
5896 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5897 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5898 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5899 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5900
5901 // down when pressure is non-zero
5902 processPressure(mapper, RAW_PRESSURE_MAX);
5903 processSync(mapper);
5904 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5905 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5906 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5907 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5908
5909 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5910 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
5911 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5912 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5913
5914 // up when pressure becomes 0, hover restored
5915 processPressure(mapper, 0);
5916 processSync(mapper);
5917 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5918 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
5919 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5920 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
5921
5922 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5923 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
5924 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5925 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5926
5927 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5928 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
5929 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5930 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5931
5932 // exit hover when pointer goes away
5933 processUp(mapper);
5934 processSync(mapper);
5935 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
5936 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
5937 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
5938 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
5939}
5940
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00005941TEST_F(SingleTouchInputMapperTest, Reset_CancelsOngoingGesture) {
5942 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005943 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00005944 prepareButtons();
5945 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00005946 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00005947
5948 // Touch down.
5949 processDown(mapper, 100, 200);
5950 processPressure(mapper, 1);
5951 processSync(mapper);
5952 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
5953 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
5954
5955 // Reset the mapper. This should cancel the ongoing gesture.
5956 resetMapper(mapper, ARBITRARY_TIME);
5957 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
5958 WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
5959
5960 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5961}
5962
Prabir Pradhanafabcde2022-09-27 19:32:43 +00005963TEST_F(SingleTouchInputMapperTest, Reset_RecreatesTouchState) {
5964 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005965 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00005966 prepareButtons();
5967 prepareAxes(POSITION | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00005968 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00005969
5970 // Set the initial state for the touch pointer.
5971 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_X, 100);
5972 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_Y, 200);
5973 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_PRESSURE, RAW_PRESSURE_MAX);
5974 mFakeEventHub->setScanCodeState(EVENTHUB_ID, BTN_TOUCH, 1);
5975
5976 // Reset the mapper. When the mapper is reset, we expect it to attempt to recreate the touch
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00005977 // state by reading the current axis values. Since there was no ongoing gesture, calling reset
5978 // does not generate any events.
5979 resetMapper(mapper, ARBITRARY_TIME);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00005980
5981 // Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
5982 // the recreated touch state to generate a down event.
5983 processSync(mapper);
5984 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
5985 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPressure(1.f))));
5986
5987 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
5988}
5989
lilinnan687e58f2022-07-19 16:00:50 +08005990TEST_F(SingleTouchInputMapperTest,
5991 Process_WhenViewportDisplayIdChanged_TouchIsCanceledAndDeviceIsReset) {
5992 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00005993 prepareDisplay(ui::ROTATION_0);
lilinnan687e58f2022-07-19 16:00:50 +08005994 prepareButtons();
5995 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00005996 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
lilinnan687e58f2022-07-19 16:00:50 +08005997 NotifyMotionArgs motionArgs;
5998
5999 // Down.
Prabir Pradhan3e5ec702022-07-29 16:26:24 +00006000 processDown(mapper, 100, 200);
lilinnan687e58f2022-07-19 16:00:50 +08006001 processSync(mapper);
6002
6003 // We should receive a down event
6004 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6005 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6006
6007 // Change display id
6008 clearViewports();
6009 prepareSecondaryDisplay(ViewportType::INTERNAL);
6010
6011 // We should receive a cancel event
6012 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6013 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
6014 // Then receive reset called
6015 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6016}
6017
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006018TEST_F(SingleTouchInputMapperTest,
6019 Process_WhenViewportActiveStatusChanged_TouchIsCanceledAndDeviceIsReset) {
6020 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006021 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006022 prepareButtons();
6023 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006024 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006025 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6026 NotifyMotionArgs motionArgs;
6027
6028 // Start a new gesture.
6029 processDown(mapper, 100, 200);
6030 processSync(mapper);
6031 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6032 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
6033
6034 // Make the viewport inactive. This will put the device in disabled mode.
6035 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6036 viewport->isActive = false;
6037 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006038 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006039
6040 // We should receive a cancel event for the ongoing gesture.
6041 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6042 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
6043 // Then we should be notified that the device was reset.
6044 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6045
6046 // No events are generated while the viewport is inactive.
6047 processMove(mapper, 101, 201);
6048 processSync(mapper);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006049 processUp(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006050 processSync(mapper);
6051 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6052
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006053 // Start a new gesture while the viewport is still inactive.
6054 processDown(mapper, 300, 400);
6055 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_X, 300);
6056 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_Y, 400);
6057 mFakeEventHub->setScanCodeState(EVENTHUB_ID, BTN_TOUCH, 1);
6058 processSync(mapper);
6059
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006060 // Make the viewport active again. The device should resume processing events.
6061 viewport->isActive = true;
6062 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006063 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006064
6065 // The device is reset because it changes back to direct mode, without generating any events.
6066 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6067 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6068
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006069 // In the next sync, the touch state that was recreated when the device was reset is reported.
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006070 processSync(mapper);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00006071 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6072 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00006073
6074 // No more events.
6075 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6076 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
6077}
6078
Prabir Pradhan211ba622022-10-31 21:09:21 +00006079TEST_F(SingleTouchInputMapperTest, ButtonIsReleasedOnTouchUp) {
6080 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006081 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan211ba622022-10-31 21:09:21 +00006082 prepareButtons();
6083 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006084 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan211ba622022-10-31 21:09:21 +00006085 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6086
6087 // Press a stylus button.
6088 processKey(mapper, BTN_STYLUS, 1);
6089 processSync(mapper);
6090
6091 // Start a touch gesture and ensure the BUTTON_PRESS event is generated.
6092 processDown(mapper, 100, 200);
6093 processSync(mapper);
6094 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6095 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6096 WithCoords(toDisplayX(100), toDisplayY(200)),
6097 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6098 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6099 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
6100 WithCoords(toDisplayX(100), toDisplayY(200)),
6101 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6102
6103 // Release the touch gesture. Ensure that the BUTTON_RELEASE event is generated even though
6104 // the button has not actually been released, since there will be no pointers through which the
6105 // button state can be reported. The event is generated at the location of the pointer before
6106 // it went up.
6107 processUp(mapper);
6108 processSync(mapper);
6109 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6110 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
6111 WithCoords(toDisplayX(100), toDisplayY(200)), WithButtonState(0))));
6112 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6113 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6114 WithCoords(toDisplayX(100), toDisplayY(200)), WithButtonState(0))));
6115}
6116
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00006117TEST_F(SingleTouchInputMapperTest, StylusButtonMotionEventsDisabled) {
6118 addConfigurationProperty("touch.deviceType", "touchScreen");
6119 prepareDisplay(ui::ROTATION_0);
6120 prepareButtons();
6121 prepareAxes(POSITION);
6122
6123 mFakePolicy->setStylusButtonMotionEventsEnabled(false);
6124
Arpit Singha8c236b2023-04-25 13:56:05 +00006125 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan7aa7ff02022-12-21 21:05:38 +00006126 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6127
6128 // Press a stylus button.
6129 processKey(mapper, BTN_STYLUS, 1);
6130 processSync(mapper);
6131
6132 // Start a touch gesture and ensure that the stylus button is not reported.
6133 processDown(mapper, 100, 200);
6134 processSync(mapper);
6135 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6136 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithButtonState(0))));
6137
6138 // Release and press the stylus button again.
6139 processKey(mapper, BTN_STYLUS, 0);
6140 processSync(mapper);
6141 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6142 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
6143 processKey(mapper, BTN_STYLUS, 1);
6144 processSync(mapper);
6145 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6146 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
6147
6148 // Release the touch gesture.
6149 processUp(mapper);
6150 processSync(mapper);
6151 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6152 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
6153
6154 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6155}
6156
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006157TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsSetToTouchNavigation_setsCorrectType) {
6158 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
6159 prepareDisplay(ui::ROTATION_0);
6160 prepareButtons();
6161 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006162 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006163 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
6164
Prabir Pradhan9cf8f322024-06-18 20:22:42 +00006165 ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION | AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
Ambrus Weisz7bc23bf2022-10-04 13:13:07 +00006166}
6167
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006168TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsChangedToTouchNavigation_updatesDeviceType) {
6169 // Initialize the device without setting device source to touch navigation.
6170 addConfigurationProperty("touch.deviceType", "touchScreen");
6171 prepareDisplay(ui::ROTATION_0);
6172 prepareButtons();
6173 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006174 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006175
6176 // Ensure that the device is created as a touchscreen, not touch navigation.
6177 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
6178
6179 // Add device type association after the device was created.
6180 mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
6181
6182 // Send update to the mapper.
6183 std::list<NotifyArgs> unused2 =
6184 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006185 InputReaderConfiguration::Change::DEVICE_TYPE /*changes*/);
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006186
6187 // Check whether device type update was successful.
Prabir Pradhan9cf8f322024-06-18 20:22:42 +00006188 ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION | AINPUT_SOURCE_TOUCHPAD, mDevice->getSources());
Ambrus Weisz7b6e16b2022-12-16 17:54:57 +00006189}
6190
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006191TEST_F(SingleTouchInputMapperTest, HoverEventsOutsidePhysicalFrameAreIgnored) {
6192 // Initialize the device without setting device source to touch navigation.
6193 addConfigurationProperty("touch.deviceType", "touchScreen");
6194 prepareDisplay(ui::ROTATION_0);
6195 prepareButtons();
6196 prepareAxes(POSITION);
6197 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
6198
6199 // Set a physical frame in the display viewport.
6200 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6201 viewport->physicalLeft = 0;
6202 viewport->physicalTop = 0;
6203 viewport->physicalRight = DISPLAY_WIDTH / 2;
6204 viewport->physicalBottom = DISPLAY_HEIGHT / 2;
6205 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006206 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006207
Arpit Singha8c236b2023-04-25 13:56:05 +00006208 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhane1e309a2022-11-29 02:54:27 +00006209
6210 // Hovering inside the physical frame produces events.
6211 processKey(mapper, BTN_TOOL_PEN, 1);
6212 processMove(mapper, RAW_X_MIN + 1, RAW_Y_MIN + 1);
6213 processSync(mapper);
6214 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6215 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)));
6216 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6217 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)));
6218
6219 // Leaving the physical frame ends the hovering gesture.
6220 processMove(mapper, RAW_X_MAX - 1, RAW_Y_MAX - 1);
6221 processSync(mapper);
6222 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6223 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT)));
6224
6225 // Moving outside the physical frame does not produce events.
6226 processMove(mapper, RAW_X_MAX - 2, RAW_Y_MAX - 2);
6227 processSync(mapper);
6228 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6229
6230 // Re-entering the physical frame produces events.
6231 processMove(mapper, RAW_X_MIN, RAW_Y_MIN);
6232 processSync(mapper);
6233 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6234 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)));
6235 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6236 WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)));
6237}
6238
Prabir Pradhan5632d622021-09-06 07:57:20 -07006239// --- TouchDisplayProjectionTest ---
6240
6241class TouchDisplayProjectionTest : public SingleTouchInputMapperTest {
6242public:
6243 // The values inside DisplayViewport are expected to be pre-rotated. This updates the current
6244 // DisplayViewport to pre-rotate the values. The viewport's physical display will be set to the
6245 // rotated equivalent of the given un-rotated physical display bounds.
Prabir Pradhana9df3162022-12-05 23:57:27 +00006246 void configurePhysicalDisplay(ui::Rotation orientation, Rect naturalPhysicalDisplay,
6247 int32_t naturalDisplayWidth = DISPLAY_WIDTH,
6248 int32_t naturalDisplayHeight = DISPLAY_HEIGHT) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006249 uint32_t inverseRotationFlags;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006250 auto rotatedWidth = naturalDisplayWidth;
6251 auto rotatedHeight = naturalDisplayHeight;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006252 switch (orientation) {
Michael Wrighta9cf4192022-12-01 23:46:39 +00006253 case ui::ROTATION_90:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006254 inverseRotationFlags = ui::Transform::ROT_270;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006255 std::swap(rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006256 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006257 case ui::ROTATION_180:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006258 inverseRotationFlags = ui::Transform::ROT_180;
6259 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006260 case ui::ROTATION_270:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006261 inverseRotationFlags = ui::Transform::ROT_90;
Prabir Pradhana9df3162022-12-05 23:57:27 +00006262 std::swap(rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006263 break;
Michael Wrighta9cf4192022-12-01 23:46:39 +00006264 case ui::ROTATION_0:
Prabir Pradhan5632d622021-09-06 07:57:20 -07006265 inverseRotationFlags = ui::Transform::ROT_0;
6266 break;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006267 }
6268
Prabir Pradhana9df3162022-12-05 23:57:27 +00006269 const ui::Transform rotation(inverseRotationFlags, rotatedWidth, rotatedHeight);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006270 const Rect rotatedPhysicalDisplay = rotation.transform(naturalPhysicalDisplay);
6271
6272 std::optional<DisplayViewport> internalViewport =
6273 *mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
6274 DisplayViewport& v = *internalViewport;
6275 v.displayId = DISPLAY_ID;
6276 v.orientation = orientation;
6277
6278 v.logicalLeft = 0;
6279 v.logicalTop = 0;
6280 v.logicalRight = 100;
6281 v.logicalBottom = 100;
6282
6283 v.physicalLeft = rotatedPhysicalDisplay.left;
6284 v.physicalTop = rotatedPhysicalDisplay.top;
6285 v.physicalRight = rotatedPhysicalDisplay.right;
6286 v.physicalBottom = rotatedPhysicalDisplay.bottom;
6287
Prabir Pradhana9df3162022-12-05 23:57:27 +00006288 v.deviceWidth = rotatedWidth;
6289 v.deviceHeight = rotatedHeight;
Prabir Pradhan5632d622021-09-06 07:57:20 -07006290
6291 v.isActive = true;
6292 v.uniqueId = UNIQUE_ID;
6293 v.type = ViewportType::INTERNAL;
6294 mFakePolicy->updateViewport(v);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006295 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006296 }
6297
6298 void assertReceivedMove(const Point& point) {
6299 NotifyMotionArgs motionArgs;
6300 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6301 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006302 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Prabir Pradhan5632d622021-09-06 07:57:20 -07006303 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], point.x, point.y,
6304 1, 0, 0, 0, 0, 0, 0, 0));
6305 }
6306};
6307
6308TEST_F(TouchDisplayProjectionTest, IgnoresTouchesOutsidePhysicalDisplay) {
6309 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006310 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006311
6312 prepareButtons();
6313 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006314 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan5632d622021-09-06 07:57:20 -07006315
6316 NotifyMotionArgs motionArgs;
6317
6318 // Configure the DisplayViewport such that the logical display maps to a subsection of
6319 // the display panel called the physical display. Here, the physical display is bounded by the
6320 // points (10, 20) and (70, 160) inside the display space, which is of the size 400 x 800.
6321 static const Rect kPhysicalDisplay{10, 20, 70, 160};
6322 static const std::array<Point, 6> kPointsOutsidePhysicalDisplay{
6323 {{-10, -10}, {0, 0}, {5, 100}, {50, 15}, {75, 100}, {50, 165}}};
6324
Michael Wrighta9cf4192022-12-01 23:46:39 +00006325 for (auto orientation : {ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180, ui::ROTATION_270}) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006326 configurePhysicalDisplay(orientation, kPhysicalDisplay);
6327
6328 // Touches outside the physical display should be ignored, and should not generate any
6329 // events. Ensure touches at the following points that lie outside of the physical display
6330 // area do not generate any events.
6331 for (const auto& point : kPointsOutsidePhysicalDisplay) {
6332 processDown(mapper, toRawX(point.x), toRawY(point.y));
6333 processSync(mapper);
6334 processUp(mapper);
6335 processSync(mapper);
6336 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled())
6337 << "Unexpected event generated for touch outside physical display at point: "
6338 << point.x << ", " << point.y;
6339 }
6340 }
6341}
6342
6343TEST_F(TouchDisplayProjectionTest, EmitsTouchDownAfterEnteringPhysicalDisplay) {
6344 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006345 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan5632d622021-09-06 07:57:20 -07006346
6347 prepareButtons();
6348 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006349 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan5632d622021-09-06 07:57:20 -07006350
6351 NotifyMotionArgs motionArgs;
6352
6353 // Configure the DisplayViewport such that the logical display maps to a subsection of
6354 // the display panel called the physical display. Here, the physical display is bounded by the
6355 // points (10, 20) and (70, 160) inside the display space, which is of the size 400 x 800.
6356 static const Rect kPhysicalDisplay{10, 20, 70, 160};
6357
Michael Wrighta9cf4192022-12-01 23:46:39 +00006358 for (auto orientation : {ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180, ui::ROTATION_270}) {
Prabir Pradhan5632d622021-09-06 07:57:20 -07006359 configurePhysicalDisplay(orientation, kPhysicalDisplay);
6360
6361 // Touches that start outside the physical display should be ignored until it enters the
6362 // physical display bounds, at which point it should generate a down event. Start a touch at
6363 // the point (5, 100), which is outside the physical display bounds.
6364 static const Point kOutsidePoint{5, 100};
6365 processDown(mapper, toRawX(kOutsidePoint.x), toRawY(kOutsidePoint.y));
6366 processSync(mapper);
6367 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6368
6369 // Move the touch into the physical display area. This should generate a pointer down.
6370 processMove(mapper, toRawX(11), toRawY(21));
6371 processSync(mapper);
6372 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6373 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006374 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Prabir Pradhan5632d622021-09-06 07:57:20 -07006375 ASSERT_NO_FATAL_FAILURE(
6376 assertPointerCoords(motionArgs.pointerCoords[0], 11, 21, 1, 0, 0, 0, 0, 0, 0, 0));
6377
6378 // Move the touch inside the physical display area. This should generate a pointer move.
6379 processMove(mapper, toRawX(69), toRawY(159));
6380 processSync(mapper);
6381 assertReceivedMove({69, 159});
6382
6383 // Move outside the physical display area. Since the pointer is already down, this should
6384 // now continue generating events.
6385 processMove(mapper, toRawX(kOutsidePoint.x), toRawY(kOutsidePoint.y));
6386 processSync(mapper);
6387 assertReceivedMove(kOutsidePoint);
6388
6389 // Release. This should generate a pointer up.
6390 processUp(mapper);
6391 processSync(mapper);
6392 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
6393 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
6394 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], kOutsidePoint.x,
6395 kOutsidePoint.y, 1, 0, 0, 0, 0, 0, 0, 0));
6396
6397 // Ensure no more events were generated.
6398 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
6399 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6400 }
6401}
6402
Prabir Pradhana9df3162022-12-05 23:57:27 +00006403// --- TouchscreenPrecisionTests ---
6404
6405// This test suite is used to ensure that touchscreen devices are scaled and configured correctly
6406// in various orientations and with different display rotations. We configure the touchscreen to
6407// have a higher resolution than that of the display by an integer scale factor in each axis so that
6408// we can enforce that coordinates match precisely as expected.
6409class TouchscreenPrecisionTestsFixture : public TouchDisplayProjectionTest,
6410 public ::testing::WithParamInterface<ui::Rotation> {
6411public:
6412 void SetUp() override {
6413 SingleTouchInputMapperTest::SetUp();
6414
6415 // Prepare the raw axes to have twice the resolution of the display in the X axis and
6416 // four times the resolution of the display in the Y axis.
6417 prepareButtons();
6418 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, PRECISION_RAW_X_MIN, PRECISION_RAW_X_MAX,
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006419 PRECISION_RAW_X_FLAT, PRECISION_RAW_X_FUZZ,
6420 PRECISION_RAW_X_RES);
Prabir Pradhana9df3162022-12-05 23:57:27 +00006421 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, PRECISION_RAW_Y_MIN, PRECISION_RAW_Y_MAX,
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006422 PRECISION_RAW_Y_FLAT, PRECISION_RAW_Y_FUZZ,
6423 PRECISION_RAW_Y_RES);
Prabir Pradhana9df3162022-12-05 23:57:27 +00006424 }
6425
6426 static const int32_t PRECISION_RAW_X_MIN = TouchInputMapperTest::RAW_X_MIN;
6427 static const int32_t PRECISION_RAW_X_MAX = PRECISION_RAW_X_MIN + DISPLAY_WIDTH * 2 - 1;
6428 static const int32_t PRECISION_RAW_Y_MIN = TouchInputMapperTest::RAW_Y_MIN;
6429 static const int32_t PRECISION_RAW_Y_MAX = PRECISION_RAW_Y_MIN + DISPLAY_HEIGHT * 4 - 1;
6430
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006431 static const int32_t PRECISION_RAW_X_RES = 50; // units per millimeter
6432 static const int32_t PRECISION_RAW_Y_RES = 100; // units per millimeter
6433
6434 static const int32_t PRECISION_RAW_X_FLAT = 16;
6435 static const int32_t PRECISION_RAW_Y_FLAT = 32;
6436
6437 static const int32_t PRECISION_RAW_X_FUZZ = 4;
6438 static const int32_t PRECISION_RAW_Y_FUZZ = 8;
6439
Prabir Pradhana9df3162022-12-05 23:57:27 +00006440 static const std::array<Point, 4> kRawCorners;
6441};
6442
6443const std::array<Point, 4> TouchscreenPrecisionTestsFixture::kRawCorners = {{
6444 {PRECISION_RAW_X_MIN, PRECISION_RAW_Y_MIN}, // left-top
6445 {PRECISION_RAW_X_MAX, PRECISION_RAW_Y_MIN}, // right-top
6446 {PRECISION_RAW_X_MAX, PRECISION_RAW_Y_MAX}, // right-bottom
6447 {PRECISION_RAW_X_MIN, PRECISION_RAW_Y_MAX}, // left-bottom
6448}};
6449
6450// Tests for how the touchscreen is oriented relative to the natural orientation of the display.
6451// For example, if a touchscreen is configured with an orientation of 90 degrees, it is a portrait
6452// touchscreen panel that is used on a device whose natural display orientation is in landscape.
6453TEST_P(TouchscreenPrecisionTestsFixture, OrientationPrecision) {
6454 enum class Orientation {
6455 ORIENTATION_0 = ui::toRotationInt(ui::ROTATION_0),
6456 ORIENTATION_90 = ui::toRotationInt(ui::ROTATION_90),
6457 ORIENTATION_180 = ui::toRotationInt(ui::ROTATION_180),
6458 ORIENTATION_270 = ui::toRotationInt(ui::ROTATION_270),
6459 ftl_last = ORIENTATION_270,
6460 };
6461 using Orientation::ORIENTATION_0, Orientation::ORIENTATION_90, Orientation::ORIENTATION_180,
6462 Orientation::ORIENTATION_270;
6463 static const std::map<Orientation, std::array<vec2, 4> /*mappedCorners*/> kMappedCorners = {
6464 {ORIENTATION_0, {{{0, 0}, {479.5, 0}, {479.5, 799.75}, {0, 799.75}}}},
6465 {ORIENTATION_90, {{{0, 479.5}, {0, 0}, {799.75, 0}, {799.75, 479.5}}}},
6466 {ORIENTATION_180, {{{479.5, 799.75}, {0, 799.75}, {0, 0}, {479.5, 0}}}},
6467 {ORIENTATION_270, {{{799.75, 0}, {799.75, 479.5}, {0, 479.5}, {0, 0}}}},
6468 };
6469
6470 const auto touchscreenOrientation = static_cast<Orientation>(ui::toRotationInt(GetParam()));
6471
6472 // Configure the touchscreen as being installed in the one of the four different orientations
6473 // relative to the display.
6474 addConfigurationProperty("touch.deviceType", "touchScreen");
6475 addConfigurationProperty("touch.orientation", ftl::enum_string(touchscreenOrientation).c_str());
6476 prepareDisplay(ui::ROTATION_0);
6477
Arpit Singha8c236b2023-04-25 13:56:05 +00006478 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhana9df3162022-12-05 23:57:27 +00006479
6480 // If the touchscreen is installed in a rotated orientation relative to the display (i.e. in
6481 // orientations of either 90 or 270) this means the display's natural resolution will be
6482 // flipped.
6483 const bool displayRotated =
6484 touchscreenOrientation == ORIENTATION_90 || touchscreenOrientation == ORIENTATION_270;
6485 const int32_t width = displayRotated ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
6486 const int32_t height = displayRotated ? DISPLAY_WIDTH : DISPLAY_HEIGHT;
6487 const Rect physicalFrame{0, 0, width, height};
6488 configurePhysicalDisplay(ui::ROTATION_0, physicalFrame, width, height);
6489
6490 const auto& expectedPoints = kMappedCorners.at(touchscreenOrientation);
6491 const float expectedPrecisionX = displayRotated ? 4 : 2;
6492 const float expectedPrecisionY = displayRotated ? 2 : 4;
6493
6494 // Test all four corners.
6495 for (int i = 0; i < 4; i++) {
6496 const auto& raw = kRawCorners[i];
6497 processDown(mapper, raw.x, raw.y);
6498 processSync(mapper);
6499 const auto& expected = expectedPoints[i];
6500 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6501 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6502 WithCoords(expected.x, expected.y),
6503 WithPrecision(expectedPrecisionX, expectedPrecisionY))))
6504 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6505 << "with touchscreen orientation "
6506 << ftl::enum_string(touchscreenOrientation).c_str() << ", expected point ("
6507 << expected.x << ", " << expected.y << ").";
6508 processUp(mapper);
6509 processSync(mapper);
6510 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6511 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6512 WithCoords(expected.x, expected.y))));
6513 }
6514}
6515
Prabir Pradhan82687402022-12-06 01:32:53 +00006516TEST_P(TouchscreenPrecisionTestsFixture, RotationPrecisionWhenOrientationAware) {
6517 static const std::map<ui::Rotation /*rotation*/, std::array<vec2, 4> /*mappedCorners*/>
6518 kMappedCorners = {
6519 {ui::ROTATION_0, {{{0, 0}, {479.5, 0}, {479.5, 799.75}, {0, 799.75}}}},
6520 {ui::ROTATION_90, {{{0.5, 0}, {480, 0}, {480, 799.75}, {0.5, 799.75}}}},
6521 {ui::ROTATION_180, {{{0.5, 0.25}, {480, 0.25}, {480, 800}, {0.5, 800}}}},
6522 {ui::ROTATION_270, {{{0, 0.25}, {479.5, 0.25}, {479.5, 800}, {0, 800}}}},
6523 };
6524
6525 const ui::Rotation displayRotation = GetParam();
6526
6527 addConfigurationProperty("touch.deviceType", "touchScreen");
6528 prepareDisplay(displayRotation);
6529
Arpit Singha8c236b2023-04-25 13:56:05 +00006530 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan82687402022-12-06 01:32:53 +00006531
6532 const auto& expectedPoints = kMappedCorners.at(displayRotation);
6533
6534 // Test all four corners.
6535 for (int i = 0; i < 4; i++) {
6536 const auto& expected = expectedPoints[i];
6537 const auto& raw = kRawCorners[i];
6538 processDown(mapper, raw.x, raw.y);
6539 processSync(mapper);
6540 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6541 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6542 WithCoords(expected.x, expected.y), WithPrecision(2, 4))))
6543 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6544 << "with display rotation " << ui::toCString(displayRotation)
6545 << ", expected point (" << expected.x << ", " << expected.y << ").";
6546 processUp(mapper);
6547 processSync(mapper);
6548 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6549 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6550 WithCoords(expected.x, expected.y))));
6551 }
6552}
6553
Prabir Pradhan3e798762022-12-02 21:02:11 +00006554TEST_P(TouchscreenPrecisionTestsFixture, RotationPrecisionOrientationAwareInOri270) {
6555 static const std::map<ui::Rotation /*orientation*/, std::array<vec2, 4> /*mappedCorners*/>
6556 kMappedCorners = {
6557 {ui::ROTATION_0, {{{799.75, 0}, {799.75, 479.5}, {0, 479.5}, {0, 0}}}},
6558 {ui::ROTATION_90, {{{800, 0}, {800, 479.5}, {0.25, 479.5}, {0.25, 0}}}},
6559 {ui::ROTATION_180, {{{800, 0.5}, {800, 480}, {0.25, 480}, {0.25, 0.5}}}},
6560 {ui::ROTATION_270, {{{799.75, 0.5}, {799.75, 480}, {0, 480}, {0, 0.5}}}},
6561 };
6562
6563 const ui::Rotation displayRotation = GetParam();
6564
6565 addConfigurationProperty("touch.deviceType", "touchScreen");
6566 addConfigurationProperty("touch.orientation", "ORIENTATION_270");
6567
Arpit Singha8c236b2023-04-25 13:56:05 +00006568 SingleTouchInputMapper& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan3e798762022-12-02 21:02:11 +00006569
6570 // Ori 270, so width and height swapped
6571 const Rect physicalFrame{0, 0, DISPLAY_HEIGHT, DISPLAY_WIDTH};
6572 prepareDisplay(displayRotation);
6573 configurePhysicalDisplay(displayRotation, physicalFrame, DISPLAY_HEIGHT, DISPLAY_WIDTH);
6574
6575 const auto& expectedPoints = kMappedCorners.at(displayRotation);
6576
6577 // Test all four corners.
6578 for (int i = 0; i < 4; i++) {
6579 const auto& expected = expectedPoints[i];
6580 const auto& raw = kRawCorners[i];
6581 processDown(mapper, raw.x, raw.y);
6582 processSync(mapper);
6583 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6584 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6585 WithCoords(expected.x, expected.y), WithPrecision(4, 2))))
6586 << "Failed to process raw point (" << raw.x << ", " << raw.y << ") "
6587 << "with display rotation " << ui::toCString(displayRotation)
6588 << ", expected point (" << expected.x << ", " << expected.y << ").";
6589 processUp(mapper);
6590 processSync(mapper);
6591 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6592 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
6593 WithCoords(expected.x, expected.y))));
6594 }
6595}
6596
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006597TEST_P(TouchscreenPrecisionTestsFixture, MotionRangesAreOrientedInRotatedDisplay) {
6598 const ui::Rotation displayRotation = GetParam();
6599
6600 addConfigurationProperty("touch.deviceType", "touchScreen");
6601 prepareDisplay(displayRotation);
6602
6603 __attribute__((unused)) SingleTouchInputMapper& mapper =
Arpit Singha8c236b2023-04-25 13:56:05 +00006604 constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan46211fb2022-12-17 00:30:39 +00006605
6606 const InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
6607 // MotionRanges use display pixels as their units
6608 const auto* xRange = deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHSCREEN);
6609 const auto* yRange = deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_Y, AINPUT_SOURCE_TOUCHSCREEN);
6610
6611 // The MotionRanges should be oriented in the rotated display's coordinate space
6612 const bool displayRotated =
6613 displayRotation == ui::ROTATION_90 || displayRotation == ui::ROTATION_270;
6614
6615 constexpr float MAX_X = 479.5;
6616 constexpr float MAX_Y = 799.75;
6617 EXPECT_EQ(xRange->min, 0.f);
6618 EXPECT_EQ(yRange->min, 0.f);
6619 EXPECT_EQ(xRange->max, displayRotated ? MAX_Y : MAX_X);
6620 EXPECT_EQ(yRange->max, displayRotated ? MAX_X : MAX_Y);
6621
6622 EXPECT_EQ(xRange->flat, 8.f);
6623 EXPECT_EQ(yRange->flat, 8.f);
6624
6625 EXPECT_EQ(xRange->fuzz, 2.f);
6626 EXPECT_EQ(yRange->fuzz, 2.f);
6627
6628 EXPECT_EQ(xRange->resolution, 25.f); // pixels per millimeter
6629 EXPECT_EQ(yRange->resolution, 25.f); // pixels per millimeter
6630}
6631
Prabir Pradhana9df3162022-12-05 23:57:27 +00006632// Run the precision tests for all rotations.
6633INSTANTIATE_TEST_SUITE_P(TouchscreenPrecisionTests, TouchscreenPrecisionTestsFixture,
6634 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
6635 ui::ROTATION_270),
6636 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
6637 return ftl::enum_string(testParamInfo.param);
6638 });
6639
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006640// --- ExternalStylusFusionTest ---
6641
6642class ExternalStylusFusionTest : public SingleTouchInputMapperTest {
6643public:
Prabir Pradhan7ff19a12024-07-29 22:40:31 +00006644 void SetUp() override {
6645 SingleTouchInputMapperTest::SetUp();
6646 mExternalStylusDeviceInfo = {};
6647 mStylusState = {};
6648 }
6649
6650 SingleTouchInputMapper& initializeInputMapperWithExternalStylus(bool supportsPressure = true) {
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006651 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00006652 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006653 prepareButtons();
6654 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00006655 auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006656
Prabir Pradhan7ff19a12024-07-29 22:40:31 +00006657 if (supportsPressure) {
6658 mExternalStylusDeviceInfo.addMotionRange(AMOTION_EVENT_AXIS_PRESSURE,
6659 AINPUT_SOURCE_STYLUS, 0.0f, 1.0f, 0.0f, 0.0f,
6660 0.0f);
6661 mStylusState.pressure = 0.f;
6662 }
6663
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006664 mStylusState.when = ARBITRARY_TIME;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006665 mStylusState.toolType = ToolType::STYLUS;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006666 mReader->getContext()->setExternalStylusDevices({mExternalStylusDeviceInfo});
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00006667 configureDevice(InputReaderConfiguration::Change::EXTERNAL_STYLUS_PRESENCE);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006668 processExternalStylusState(mapper);
6669 return mapper;
6670 }
6671
6672 std::list<NotifyArgs> processExternalStylusState(InputMapper& mapper) {
6673 std::list<NotifyArgs> generatedArgs = mapper.updateExternalStylusState(mStylusState);
6674 for (const NotifyArgs& args : generatedArgs) {
6675 mFakeListener->notify(args);
6676 }
6677 // Loop the reader to flush the input listener queue.
6678 mReader->loopOnce();
6679 return generatedArgs;
6680 }
6681
6682protected:
6683 StylusState mStylusState{};
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006684
6685 void testStartFusedStylusGesture(SingleTouchInputMapper& mapper) {
6686 auto toolTypeSource =
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006687 AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006688
6689 // The first pointer is withheld.
6690 processDown(mapper, 100, 200);
6691 processSync(mapper);
6692 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6693 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6694 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6695
6696 // The external stylus reports pressure. The withheld finger pointer is released as a
6697 // stylus.
6698 mStylusState.pressure = 1.f;
6699 processExternalStylusState(mapper);
6700 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6701 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6702 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6703
6704 // Subsequent pointer events are not withheld.
6705 processMove(mapper, 101, 201);
6706 processSync(mapper);
6707 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6708 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6709
6710 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6711 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6712 }
6713
6714 void testSuccessfulFusionGesture(SingleTouchInputMapper& mapper) {
6715 ASSERT_NO_FATAL_FAILURE(testStartFusedStylusGesture(mapper));
6716
6717 // Releasing the touch pointer ends the gesture.
6718 processUp(mapper);
6719 processSync(mapper);
6720 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006721 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(STYLUS_FUSION_SOURCE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006722 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006723
6724 mStylusState.pressure = 0.f;
6725 processExternalStylusState(mapper);
6726 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6727 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6728 }
6729
6730 void testUnsuccessfulFusionGesture(SingleTouchInputMapper& mapper) {
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006731 // When stylus fusion is not successful, events should be reported with the original source.
6732 // In this case, it is from a touchscreen.
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006733 auto toolTypeSource =
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006734 AllOf(WithSource(AINPUT_SOURCE_TOUCHSCREEN), WithToolType(ToolType::FINGER));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006735
6736 // The first pointer is withheld when an external stylus is connected,
6737 // and a timeout is requested.
6738 processDown(mapper, 100, 200);
6739 processSync(mapper);
6740 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6741 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6742 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6743
6744 // If the timeout expires early, it is requested again.
6745 handleTimeout(mapper, ARBITRARY_TIME + 1);
6746 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasRequested(
6747 ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT));
6748
6749 // When the timeout expires, the withheld touch is released as a finger pointer.
6750 handleTimeout(mapper, ARBITRARY_TIME + EXTERNAL_STYLUS_DATA_TIMEOUT);
6751 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6752 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6753
6754 // Subsequent pointer events are not withheld.
6755 processMove(mapper, 101, 201);
6756 processSync(mapper);
6757 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6758 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6759 processUp(mapper);
6760 processSync(mapper);
6761 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6762 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP))));
6763
6764 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6765 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6766 }
6767
6768private:
6769 InputDeviceInfo mExternalStylusDeviceInfo{};
6770};
6771
Prabir Pradhan7ff19a12024-07-29 22:40:31 +00006772TEST_F(ExternalStylusFusionTest, UsesBluetoothStylusSourceWithPressure) {
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006773 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006774 ASSERT_EQ(STYLUS_FUSION_SOURCE, mapper.getSources());
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006775}
6776
Prabir Pradhan7ff19a12024-07-29 22:40:31 +00006777TEST_F(ExternalStylusFusionTest, DoesNotUseBluetoothStylusSourceWithoutPressure) {
6778 SingleTouchInputMapper& mapper =
6779 initializeInputMapperWithExternalStylus(/*supportsPressure=*/false);
6780 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
6781}
6782
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006783TEST_F(ExternalStylusFusionTest, UnsuccessfulFusion) {
6784 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6785 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6786}
6787
6788TEST_F(ExternalStylusFusionTest, SuccessfulFusion_TouchFirst) {
6789 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6790 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6791}
6792
6793// Test a successful stylus fusion gesture where the pressure is reported by the external
6794// before the touch is reported by the touchscreen.
6795TEST_F(ExternalStylusFusionTest, SuccessfulFusion_PressureFirst) {
6796 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006797 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006798
6799 // The external stylus reports pressure first. It is ignored for now.
6800 mStylusState.pressure = 1.f;
6801 processExternalStylusState(mapper);
6802 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6803 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6804
6805 // When the touch goes down afterwards, it is reported as a stylus pointer.
6806 processDown(mapper, 100, 200);
6807 processSync(mapper);
6808 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6809 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN))));
6810 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6811
6812 processMove(mapper, 101, 201);
6813 processSync(mapper);
6814 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6815 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
6816 processUp(mapper);
6817 processSync(mapper);
6818 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6819 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP))));
6820
6821 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6822 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6823}
6824
6825TEST_F(ExternalStylusFusionTest, FusionIsRepeatedForEachNewGesture) {
6826 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
6827
6828 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6829 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6830
6831 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6832 ASSERT_NO_FATAL_FAILURE(testSuccessfulFusionGesture(mapper));
6833 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6834 ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
6835}
6836
6837TEST_F(ExternalStylusFusionTest, FusedPointerReportsPressureChanges) {
6838 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006839 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006840
6841 mStylusState.pressure = 0.8f;
6842 processExternalStylusState(mapper);
6843 processDown(mapper, 100, 200);
6844 processSync(mapper);
6845 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6846 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
6847 WithPressure(0.8f))));
6848 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6849
6850 // The external stylus reports a pressure change. We wait for some time for a touch event.
6851 mStylusState.pressure = 0.6f;
6852 processExternalStylusState(mapper);
6853 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6854 ASSERT_NO_FATAL_FAILURE(
6855 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6856
6857 // If a touch is reported within the timeout, it reports the updated pressure.
6858 processMove(mapper, 101, 201);
6859 processSync(mapper);
6860 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6861 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6862 WithPressure(0.6f))));
6863 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6864
6865 // There is another pressure change.
6866 mStylusState.pressure = 0.5f;
6867 processExternalStylusState(mapper);
6868 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6869 ASSERT_NO_FATAL_FAILURE(
6870 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6871
6872 // If a touch is not reported within the timeout, a move event is generated to report
6873 // the new pressure.
6874 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
6875 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6876 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6877 WithPressure(0.5f))));
6878
6879 // If a zero pressure is reported before the touch goes up, the previous pressure value is
6880 // repeated indefinitely.
6881 mStylusState.pressure = 0.0f;
6882 processExternalStylusState(mapper);
6883 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6884 ASSERT_NO_FATAL_FAILURE(
6885 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6886 processMove(mapper, 102, 202);
6887 processSync(mapper);
6888 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6889 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6890 WithPressure(0.5f))));
6891 processMove(mapper, 103, 203);
6892 processSync(mapper);
6893 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6894 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6895 WithPressure(0.5f))));
6896
6897 processUp(mapper);
6898 processSync(mapper);
6899 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006900 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(STYLUS_FUSION_SOURCE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006901 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006902
6903 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6904 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6905}
6906
6907TEST_F(ExternalStylusFusionTest, FusedPointerReportsToolTypeChanges) {
6908 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006909 auto source = WithSource(STYLUS_FUSION_SOURCE);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006910
6911 mStylusState.pressure = 1.f;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006912 mStylusState.toolType = ToolType::ERASER;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006913 processExternalStylusState(mapper);
6914 processDown(mapper, 100, 200);
6915 processSync(mapper);
6916 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6917 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006918 WithToolType(ToolType::ERASER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006919 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6920
6921 // The external stylus reports a tool change. We wait for some time for a touch event.
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006922 mStylusState.toolType = ToolType::STYLUS;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006923 processExternalStylusState(mapper);
6924 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6925 ASSERT_NO_FATAL_FAILURE(
6926 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6927
6928 // If a touch is reported within the timeout, it reports the updated pressure.
6929 processMove(mapper, 101, 201);
6930 processSync(mapper);
6931 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6932 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006933 WithToolType(ToolType::STYLUS))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006934 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6935
6936 // There is another tool type change.
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006937 mStylusState.toolType = ToolType::FINGER;
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006938 processExternalStylusState(mapper);
6939 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6940 ASSERT_NO_FATAL_FAILURE(
6941 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6942
6943 // If a touch is not reported within the timeout, a move event is generated to report
6944 // the new tool type.
6945 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
6946 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6947 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006948 WithToolType(ToolType::FINGER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006949
6950 processUp(mapper);
6951 processSync(mapper);
6952 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6953 AllOf(source, WithMotionAction(AMOTION_EVENT_ACTION_UP),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006954 WithToolType(ToolType::FINGER))));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006955
6956 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6957 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6958}
6959
6960TEST_F(ExternalStylusFusionTest, FusedPointerReportsButtons) {
6961 SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
Prabir Pradhanb08a0e82023-09-14 22:28:32 +00006962 auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006963
6964 ASSERT_NO_FATAL_FAILURE(testStartFusedStylusGesture(mapper));
6965
6966 // The external stylus reports a button change. We wait for some time for a touch event.
6967 mStylusState.buttons = AMOTION_EVENT_BUTTON_STYLUS_PRIMARY;
6968 processExternalStylusState(mapper);
6969 ASSERT_NO_FATAL_FAILURE(
6970 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6971
6972 // If a touch is reported within the timeout, it reports the updated button state.
6973 processMove(mapper, 101, 201);
6974 processSync(mapper);
6975 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6976 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6977 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6978 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6979 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
6980 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
6981 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
6982
6983 // The button is now released.
6984 mStylusState.buttons = 0;
6985 processExternalStylusState(mapper);
6986 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
6987 ASSERT_NO_FATAL_FAILURE(
6988 mReader->getContext()->assertTimeoutWasRequested(ARBITRARY_TIME + TOUCH_DATA_TIMEOUT));
6989
6990 // If a touch is not reported within the timeout, a move event is generated to report
6991 // the new button state.
6992 handleTimeout(mapper, ARBITRARY_TIME + TOUCH_DATA_TIMEOUT);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00006993 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
6994 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
6995 WithButtonState(0))));
6996 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhan124ea442022-10-28 20:27:44 +00006997 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
6998 WithButtonState(0))));
6999
7000 processUp(mapper);
7001 processSync(mapper);
7002 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +00007003 AllOf(toolTypeSource, WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
7004
7005 ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
7006 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7007}
7008
Michael Wrightd02c5b62014-02-10 15:10:22 -08007009// --- MultiTouchInputMapperTest ---
7010
7011class MultiTouchInputMapperTest : public TouchInputMapperTest {
7012protected:
7013 void prepareAxes(int axes);
7014
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007015 void processPosition(MultiTouchInputMapper& mapper, int32_t x, int32_t y);
7016 void processTouchMajor(MultiTouchInputMapper& mapper, int32_t touchMajor);
7017 void processTouchMinor(MultiTouchInputMapper& mapper, int32_t touchMinor);
7018 void processToolMajor(MultiTouchInputMapper& mapper, int32_t toolMajor);
7019 void processToolMinor(MultiTouchInputMapper& mapper, int32_t toolMinor);
7020 void processOrientation(MultiTouchInputMapper& mapper, int32_t orientation);
7021 void processPressure(MultiTouchInputMapper& mapper, int32_t pressure);
7022 void processDistance(MultiTouchInputMapper& mapper, int32_t distance);
7023 void processId(MultiTouchInputMapper& mapper, int32_t id);
7024 void processSlot(MultiTouchInputMapper& mapper, int32_t slot);
7025 void processToolType(MultiTouchInputMapper& mapper, int32_t toolType);
7026 void processKey(MultiTouchInputMapper& mapper, int32_t code, int32_t value);
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00007027 void processHidUsage(MultiTouchInputMapper& mapper, int32_t usageCode, int32_t value);
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007028 void processMTSync(MultiTouchInputMapper& mapper);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00007029 void processSync(MultiTouchInputMapper& mapper, nsecs_t eventTime = ARBITRARY_TIME,
7030 nsecs_t readTime = READ_TIME);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007031};
7032
7033void MultiTouchInputMapperTest::prepareAxes(int axes) {
7034 if (axes & POSITION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007035 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
7036 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007037 }
7038 if (axes & TOUCH) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007039 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN,
7040 RAW_TOUCH_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007041 if (axes & MINOR) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007042 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN,
7043 RAW_TOUCH_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007044 }
7045 }
7046 if (axes & TOOL) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007047 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7048 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007049 if (axes & MINOR) {
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007050 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MIN,
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007051 RAW_TOOL_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007052 }
7053 }
7054 if (axes & ORIENTATION) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007055 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_ORIENTATION, RAW_ORIENTATION_MIN,
7056 RAW_ORIENTATION_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007057 }
7058 if (axes & PRESSURE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007059 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_PRESSURE, RAW_PRESSURE_MIN,
7060 RAW_PRESSURE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007061 }
7062 if (axes & DISTANCE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007063 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_DISTANCE, RAW_DISTANCE_MIN,
7064 RAW_DISTANCE_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007065 }
7066 if (axes & ID) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007067 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TRACKING_ID, RAW_ID_MIN, RAW_ID_MAX, 0,
7068 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007069 }
7070 if (axes & SLOT) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007071 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_SLOT, RAW_SLOT_MIN, RAW_SLOT_MAX, 0, 0);
7072 mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007073 }
7074 if (axes & TOOL_TYPE) {
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08007075 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007076 }
7077}
7078
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007079void MultiTouchInputMapperTest::processPosition(MultiTouchInputMapper& mapper, int32_t x,
7080 int32_t y) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007081 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
7082 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007083}
7084
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007085void MultiTouchInputMapperTest::processTouchMajor(MultiTouchInputMapper& mapper,
7086 int32_t touchMajor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007087 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOUCH_MAJOR, touchMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007088}
7089
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007090void MultiTouchInputMapperTest::processTouchMinor(MultiTouchInputMapper& mapper,
7091 int32_t touchMinor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007092 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOUCH_MINOR, touchMinor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007093}
7094
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007095void MultiTouchInputMapperTest::processToolMajor(MultiTouchInputMapper& mapper, int32_t toolMajor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007096 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_WIDTH_MAJOR, toolMajor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007097}
7098
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007099void MultiTouchInputMapperTest::processToolMinor(MultiTouchInputMapper& mapper, int32_t toolMinor) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007100 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_WIDTH_MINOR, toolMinor);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007101}
7102
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007103void MultiTouchInputMapperTest::processOrientation(MultiTouchInputMapper& mapper,
7104 int32_t orientation) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007105 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_ORIENTATION, orientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007106}
7107
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007108void MultiTouchInputMapperTest::processPressure(MultiTouchInputMapper& mapper, int32_t pressure) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007109 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_PRESSURE, pressure);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007110}
7111
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007112void MultiTouchInputMapperTest::processDistance(MultiTouchInputMapper& mapper, int32_t distance) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007113 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_DISTANCE, distance);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007114}
7115
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007116void MultiTouchInputMapperTest::processId(MultiTouchInputMapper& mapper, int32_t id) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007117 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TRACKING_ID, id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007118}
7119
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007120void MultiTouchInputMapperTest::processSlot(MultiTouchInputMapper& mapper, int32_t slot) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007121 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_SLOT, slot);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007122}
7123
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007124void MultiTouchInputMapperTest::processToolType(MultiTouchInputMapper& mapper, int32_t toolType) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007125 process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_TOOL_TYPE, toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007126}
7127
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007128void MultiTouchInputMapperTest::processKey(MultiTouchInputMapper& mapper, int32_t code,
7129 int32_t value) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007130 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, code, value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007131}
7132
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00007133void MultiTouchInputMapperTest::processHidUsage(MultiTouchInputMapper& mapper, int32_t usageCode,
7134 int32_t value) {
7135 process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, usageCode);
7136 process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, value);
7137}
7138
Nathaniel R. Lewisf4916ef2020-01-14 11:57:18 -08007139void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper& mapper) {
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00007140 process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_MT_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007141}
7142
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00007143void MultiTouchInputMapperTest::processSync(MultiTouchInputMapper& mapper, nsecs_t eventTime,
7144 nsecs_t readTime) {
7145 process(mapper, eventTime, readTime, EV_SYN, SYN_REPORT, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007146}
7147
Michael Wrightd02c5b62014-02-10 15:10:22 -08007148TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackingIds) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007149 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007150 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007151 prepareAxes(POSITION);
7152 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007153 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007154
arthurhungdcef2dc2020-08-11 14:47:50 +08007155 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007156
7157 NotifyMotionArgs motionArgs;
7158
7159 // Two fingers down at once.
7160 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7161 processPosition(mapper, x1, y1);
7162 processMTSync(mapper);
7163 processPosition(mapper, x2, y2);
7164 processMTSync(mapper);
7165 processSync(mapper);
7166
7167 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7168 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7169 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7170 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7171 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7172 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
7173 ASSERT_EQ(0, motionArgs.flags);
7174 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7175 ASSERT_EQ(0, motionArgs.buttonState);
7176 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007177 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007178 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007179 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007180 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7181 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7182 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7183 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7184 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7185
7186 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7187 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7188 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7189 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7190 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007191 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007192 ASSERT_EQ(0, motionArgs.flags);
7193 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7194 ASSERT_EQ(0, motionArgs.buttonState);
7195 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007196 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007197 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007198 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007199 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007200 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007201 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7202 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7203 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7204 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7205 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7206 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7207 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7208
7209 // Move.
7210 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7211 processPosition(mapper, x1, y1);
7212 processMTSync(mapper);
7213 processPosition(mapper, x2, y2);
7214 processMTSync(mapper);
7215 processSync(mapper);
7216
7217 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7218 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7219 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7220 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7221 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7222 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7223 ASSERT_EQ(0, motionArgs.flags);
7224 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7225 ASSERT_EQ(0, motionArgs.buttonState);
7226 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007227 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007228 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007229 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007230 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007231 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007232 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7233 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7234 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7235 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7236 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7237 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7238 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7239
7240 // First finger up.
7241 x2 += 15; y2 -= 20;
7242 processPosition(mapper, x2, y2);
7243 processMTSync(mapper);
7244 processSync(mapper);
7245
7246 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7247 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7248 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7249 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7250 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007251 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007252 ASSERT_EQ(0, motionArgs.flags);
7253 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7254 ASSERT_EQ(0, motionArgs.buttonState);
7255 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007256 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007257 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007258 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007259 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007260 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007261 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7262 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7263 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7264 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7265 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7266 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7267 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7268
7269 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7270 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7271 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7272 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7273 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7274 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7275 ASSERT_EQ(0, motionArgs.flags);
7276 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7277 ASSERT_EQ(0, motionArgs.buttonState);
7278 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007279 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007280 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007281 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007282 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7283 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7284 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7285 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7286 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7287
7288 // Move.
7289 x2 += 20; y2 -= 25;
7290 processPosition(mapper, x2, y2);
7291 processMTSync(mapper);
7292 processSync(mapper);
7293
7294 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7295 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7296 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7297 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7298 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7299 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7300 ASSERT_EQ(0, motionArgs.flags);
7301 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7302 ASSERT_EQ(0, motionArgs.buttonState);
7303 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007304 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007305 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007306 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007307 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7308 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7309 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7310 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7311 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7312
7313 // New finger down.
7314 int32_t x3 = 700, y3 = 300;
7315 processPosition(mapper, x2, y2);
7316 processMTSync(mapper);
7317 processPosition(mapper, x3, y3);
7318 processMTSync(mapper);
7319 processSync(mapper);
7320
7321 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7322 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7323 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7324 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7325 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007326 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007327 ASSERT_EQ(0, motionArgs.flags);
7328 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7329 ASSERT_EQ(0, motionArgs.buttonState);
7330 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007331 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007332 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007333 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007334 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007335 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007336 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7337 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7338 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7339 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7340 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7341 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7342 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7343
7344 // Second finger up.
7345 x3 += 30; y3 -= 20;
7346 processPosition(mapper, x3, y3);
7347 processMTSync(mapper);
7348 processSync(mapper);
7349
7350 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7351 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7352 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7353 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7354 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007355 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007356 ASSERT_EQ(0, motionArgs.flags);
7357 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7358 ASSERT_EQ(0, motionArgs.buttonState);
7359 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007360 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007361 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007362 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007363 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007364 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007365 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7366 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7367 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7368 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7369 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7370 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7371 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7372
7373 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7374 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7375 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7376 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7377 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7378 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
7379 ASSERT_EQ(0, motionArgs.flags);
7380 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7381 ASSERT_EQ(0, motionArgs.buttonState);
7382 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007383 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007384 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007385 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007386 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7387 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7388 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7389 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7390 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7391
7392 // Last finger up.
7393 processMTSync(mapper);
7394 processSync(mapper);
7395
7396 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7397 ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
7398 ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
7399 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
7400 ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
7401 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
7402 ASSERT_EQ(0, motionArgs.flags);
7403 ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
7404 ASSERT_EQ(0, motionArgs.buttonState);
7405 ASSERT_EQ(0, motionArgs.edgeFlags);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007406 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007407 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007408 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007409 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7410 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7411 ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
7412 ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
7413 ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
7414
7415 // Should not have sent any more keys or motions.
7416 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7417 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7418}
7419
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007420TEST_F(MultiTouchInputMapperTest, AxisResolution_IsPopulated) {
7421 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007422 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007423
7424 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, /*flat*/ 0,
7425 /*fuzz*/ 0, /*resolution*/ 10);
7426 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, /*flat*/ 0,
7427 /*fuzz*/ 0, /*resolution*/ 11);
7428 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX,
7429 /*flat*/ 0, /*fuzz*/ 0, /*resolution*/ 12);
7430 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX,
7431 /*flat*/ 0, /*fuzz*/ 0, /*resolution*/ 13);
7432 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7433 /*flat*/ 0, /*flat*/ 0, /*resolution*/ 14);
7434 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
7435 /*flat*/ 0, /*flat*/ 0, /*resolution*/ 15);
7436
Arpit Singha8c236b2023-04-25 13:56:05 +00007437 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007438
7439 // X and Y axes
7440 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_X, 10 / X_PRECISION);
7441 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_Y, 11 / Y_PRECISION);
7442 // Touch major and minor
7443 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOUCH_MAJOR, 12 * GEOMETRIC_SCALE);
7444 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOUCH_MINOR, 13 * GEOMETRIC_SCALE);
7445 // Tool major and minor
7446 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOOL_MAJOR, 14 * GEOMETRIC_SCALE);
7447 assertAxisResolution(mapper, AMOTION_EVENT_AXIS_TOOL_MINOR, 15 * GEOMETRIC_SCALE);
7448}
7449
7450TEST_F(MultiTouchInputMapperTest, TouchMajorAndMinorAxes_DoNotAppearIfNotSupported) {
7451 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007452 prepareDisplay(ui::ROTATION_0);
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007453
7454 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, /*flat*/ 0,
7455 /*fuzz*/ 0, /*resolution*/ 10);
7456 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, /*flat*/ 0,
7457 /*fuzz*/ 0, /*resolution*/ 11);
7458
7459 // We do not add ABS_MT_TOUCH_MAJOR / MINOR or ABS_MT_WIDTH_MAJOR / MINOR axes
7460
Arpit Singha8c236b2023-04-25 13:56:05 +00007461 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou12c0fcb2021-12-17 13:40:44 -08007462
7463 // Touch major and minor
7464 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOUCH_MAJOR);
7465 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOUCH_MINOR);
7466 // Tool major and minor
7467 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOOL_MAJOR);
7468 assertAxisNotPresent(mapper, AMOTION_EVENT_AXIS_TOOL_MINOR);
7469}
7470
Michael Wrightd02c5b62014-02-10 15:10:22 -08007471TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingIds) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007472 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007473 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007474 prepareAxes(POSITION | ID);
7475 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007476 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007477
arthurhungdcef2dc2020-08-11 14:47:50 +08007478 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007479
7480 NotifyMotionArgs motionArgs;
7481
7482 // Two fingers down at once.
7483 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7484 processPosition(mapper, x1, y1);
7485 processId(mapper, 1);
7486 processMTSync(mapper);
7487 processPosition(mapper, x2, y2);
7488 processId(mapper, 2);
7489 processMTSync(mapper);
7490 processSync(mapper);
7491
7492 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7493 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007494 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007495 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007496 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007497 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7498 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7499
7500 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007501 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007502 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007503 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007504 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007505 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007506 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007507 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7508 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7509 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7510 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7511
7512 // Move.
7513 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7514 processPosition(mapper, x1, y1);
7515 processId(mapper, 1);
7516 processMTSync(mapper);
7517 processPosition(mapper, x2, y2);
7518 processId(mapper, 2);
7519 processMTSync(mapper);
7520 processSync(mapper);
7521
7522 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7523 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007524 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007525 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007526 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007527 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007528 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007529 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7530 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7531 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7532 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7533
7534 // First finger up.
7535 x2 += 15; y2 -= 20;
7536 processPosition(mapper, x2, y2);
7537 processId(mapper, 2);
7538 processMTSync(mapper);
7539 processSync(mapper);
7540
7541 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007542 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007543 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007544 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007545 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007546 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007547 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007548 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7549 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7550 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7551 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7552
7553 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7554 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007555 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007556 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007557 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007558 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7559 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7560
7561 // Move.
7562 x2 += 20; y2 -= 25;
7563 processPosition(mapper, x2, y2);
7564 processId(mapper, 2);
7565 processMTSync(mapper);
7566 processSync(mapper);
7567
7568 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7569 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007570 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007571 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007572 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007573 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7574 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7575
7576 // New finger down.
7577 int32_t x3 = 700, y3 = 300;
7578 processPosition(mapper, x2, y2);
7579 processId(mapper, 2);
7580 processMTSync(mapper);
7581 processPosition(mapper, x3, y3);
7582 processId(mapper, 3);
7583 processMTSync(mapper);
7584 processSync(mapper);
7585
7586 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007587 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007588 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007589 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007590 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007591 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007592 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007593 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7594 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7595 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7596 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7597
7598 // Second finger up.
7599 x3 += 30; y3 -= 20;
7600 processPosition(mapper, x3, y3);
7601 processId(mapper, 3);
7602 processMTSync(mapper);
7603 processSync(mapper);
7604
7605 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007606 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007607 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007608 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007609 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007610 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007611 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007612 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7613 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7614 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7615 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7616
7617 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7618 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007619 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007620 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007621 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007622 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7623 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7624
7625 // Last finger up.
7626 processMTSync(mapper);
7627 processSync(mapper);
7628
7629 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7630 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007631 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007632 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007633 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007634 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7635 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7636
7637 // Should not have sent any more keys or motions.
7638 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7639 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7640}
7641
7642TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithSlots) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007643 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007644 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007645 prepareAxes(POSITION | ID | SLOT);
7646 prepareVirtualKeys();
Arpit Singha8c236b2023-04-25 13:56:05 +00007647 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007648
arthurhungdcef2dc2020-08-11 14:47:50 +08007649 mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007650
7651 NotifyMotionArgs motionArgs;
7652
7653 // Two fingers down at once.
7654 int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
7655 processPosition(mapper, x1, y1);
7656 processId(mapper, 1);
7657 processSlot(mapper, 1);
7658 processPosition(mapper, x2, y2);
7659 processId(mapper, 2);
7660 processSync(mapper);
7661
7662 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7663 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007664 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007665 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007666 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007667 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7668 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7669
7670 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007671 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007672 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007673 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007674 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007675 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007676 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007677 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7678 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7679 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7680 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7681
7682 // Move.
7683 x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
7684 processSlot(mapper, 0);
7685 processPosition(mapper, x1, y1);
7686 processSlot(mapper, 1);
7687 processPosition(mapper, x2, y2);
7688 processSync(mapper);
7689
7690 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7691 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007692 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007693 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007694 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007695 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007696 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007697 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7698 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7699 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7700 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7701
7702 // First finger up.
7703 x2 += 15; y2 -= 20;
7704 processSlot(mapper, 0);
7705 processId(mapper, -1);
7706 processSlot(mapper, 1);
7707 processPosition(mapper, x2, y2);
7708 processSync(mapper);
7709
7710 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007711 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007712 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007713 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007714 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007715 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007716 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007717 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7718 toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
7719 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7720 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7721
7722 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7723 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007724 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007725 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007726 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007727 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7728 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7729
7730 // Move.
7731 x2 += 20; y2 -= 25;
7732 processPosition(mapper, x2, y2);
7733 processSync(mapper);
7734
7735 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7736 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007737 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007738 ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007739 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007740 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7741 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7742
7743 // New finger down.
7744 int32_t x3 = 700, y3 = 300;
7745 processPosition(mapper, x2, y2);
7746 processSlot(mapper, 0);
7747 processId(mapper, 3);
7748 processPosition(mapper, x3, y3);
7749 processSync(mapper);
7750
7751 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007752 ASSERT_EQ(ACTION_POINTER_0_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007753 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007754 ASSERT_EQ(0, 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_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007757 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007758 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7759 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7760 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7761 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7762
7763 // Second finger up.
7764 x3 += 30; y3 -= 20;
7765 processSlot(mapper, 1);
7766 processId(mapper, -1);
7767 processSlot(mapper, 0);
7768 processPosition(mapper, x3, y3);
7769 processSync(mapper);
7770
7771 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007772 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007773 ASSERT_EQ(size_t(2), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007774 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007775 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007776 ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007777 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007778 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7779 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7780 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
7781 toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
7782
7783 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7784 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007785 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007786 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007787 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007788 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7789 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7790
7791 // Last finger up.
7792 processId(mapper, -1);
7793 processSync(mapper);
7794
7795 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
7796 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007797 ASSERT_EQ(size_t(1), motionArgs.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007798 ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007799 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007800 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
7801 toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
7802
7803 // Should not have sent any more keys or motions.
7804 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
7805 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
7806}
7807
7808TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007809 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007810 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007811 prepareAxes(POSITION | TOUCH | TOOL | PRESSURE | ORIENTATION | ID | MINOR | DISTANCE);
Arpit Singha8c236b2023-04-25 13:56:05 +00007812 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007813
7814 // These calculations are based on the input device calibration documentation.
7815 int32_t rawX = 100;
7816 int32_t rawY = 200;
7817 int32_t rawTouchMajor = 7;
7818 int32_t rawTouchMinor = 6;
7819 int32_t rawToolMajor = 9;
7820 int32_t rawToolMinor = 8;
7821 int32_t rawPressure = 11;
7822 int32_t rawDistance = 0;
7823 int32_t rawOrientation = 3;
7824 int32_t id = 5;
7825
7826 float x = toDisplayX(rawX);
7827 float y = toDisplayY(rawY);
7828 float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
7829 float size = avg(rawTouchMajor, rawTouchMinor) / RAW_TOUCH_MAX;
7830 float toolMajor = float(rawToolMajor) * GEOMETRIC_SCALE;
7831 float toolMinor = float(rawToolMinor) * GEOMETRIC_SCALE;
7832 float touchMajor = float(rawTouchMajor) * GEOMETRIC_SCALE;
7833 float touchMinor = float(rawTouchMinor) * GEOMETRIC_SCALE;
7834 float orientation = float(rawOrientation) / RAW_ORIENTATION_MAX * M_PI_2;
7835 float distance = float(rawDistance);
7836
7837 processPosition(mapper, rawX, rawY);
7838 processTouchMajor(mapper, rawTouchMajor);
7839 processTouchMinor(mapper, rawTouchMinor);
7840 processToolMajor(mapper, rawToolMajor);
7841 processToolMinor(mapper, rawToolMinor);
7842 processPressure(mapper, rawPressure);
7843 processOrientation(mapper, rawOrientation);
7844 processDistance(mapper, rawDistance);
7845 processId(mapper, id);
7846 processMTSync(mapper);
7847 processSync(mapper);
7848
7849 NotifyMotionArgs args;
7850 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7851 ASSERT_EQ(0, args.pointerProperties[0].id);
7852 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7853 x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor,
7854 orientation, distance));
Prabir Pradhan9a53b552024-06-04 02:59:40 +00007855 ASSERT_EQ(args.flags, AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007856}
7857
7858TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_GeometricCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007859 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007860 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007861 prepareAxes(POSITION | TOUCH | TOOL | MINOR);
7862 addConfigurationProperty("touch.size.calibration", "geometric");
Arpit Singha8c236b2023-04-25 13:56:05 +00007863 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007864
7865 // These calculations are based on the input device calibration documentation.
7866 int32_t rawX = 100;
7867 int32_t rawY = 200;
7868 int32_t rawTouchMajor = 140;
7869 int32_t rawTouchMinor = 120;
7870 int32_t rawToolMajor = 180;
7871 int32_t rawToolMinor = 160;
7872
7873 float x = toDisplayX(rawX);
7874 float y = toDisplayY(rawY);
7875 float size = avg(rawTouchMajor, rawTouchMinor) / RAW_TOUCH_MAX;
7876 float toolMajor = float(rawToolMajor) * GEOMETRIC_SCALE;
7877 float toolMinor = float(rawToolMinor) * GEOMETRIC_SCALE;
7878 float touchMajor = float(rawTouchMajor) * GEOMETRIC_SCALE;
7879 float touchMinor = float(rawTouchMinor) * GEOMETRIC_SCALE;
7880
7881 processPosition(mapper, rawX, rawY);
7882 processTouchMajor(mapper, rawTouchMajor);
7883 processTouchMinor(mapper, rawTouchMinor);
7884 processToolMajor(mapper, rawToolMajor);
7885 processToolMinor(mapper, rawToolMinor);
7886 processMTSync(mapper);
7887 processSync(mapper);
7888
7889 NotifyMotionArgs args;
7890 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7891 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7892 x, y, 1.0f, size, touchMajor, touchMinor, toolMajor, toolMinor, 0, 0));
7893}
7894
7895TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_SummedLinearCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007896 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007897 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007898 prepareAxes(POSITION | TOUCH | TOOL);
7899 addConfigurationProperty("touch.size.calibration", "diameter");
7900 addConfigurationProperty("touch.size.scale", "10");
7901 addConfigurationProperty("touch.size.bias", "160");
7902 addConfigurationProperty("touch.size.isSummed", "1");
Arpit Singha8c236b2023-04-25 13:56:05 +00007903 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007904
7905 // These calculations are based on the input device calibration documentation.
7906 // Note: We only provide a single common touch/tool value because the device is assumed
7907 // not to emit separate values for each pointer (isSummed = 1).
7908 int32_t rawX = 100;
7909 int32_t rawY = 200;
7910 int32_t rawX2 = 150;
7911 int32_t rawY2 = 250;
7912 int32_t rawTouchMajor = 5;
7913 int32_t rawToolMajor = 8;
7914
7915 float x = toDisplayX(rawX);
7916 float y = toDisplayY(rawY);
7917 float x2 = toDisplayX(rawX2);
7918 float y2 = toDisplayY(rawY2);
7919 float size = float(rawTouchMajor) / 2 / RAW_TOUCH_MAX;
7920 float touch = float(rawTouchMajor) / 2 * 10.0f + 160.0f;
7921 float tool = float(rawToolMajor) / 2 * 10.0f + 160.0f;
7922
7923 processPosition(mapper, rawX, rawY);
7924 processTouchMajor(mapper, rawTouchMajor);
7925 processToolMajor(mapper, rawToolMajor);
7926 processMTSync(mapper);
7927 processPosition(mapper, rawX2, rawY2);
7928 processTouchMajor(mapper, rawTouchMajor);
7929 processToolMajor(mapper, rawToolMajor);
7930 processMTSync(mapper);
7931 processSync(mapper);
7932
7933 NotifyMotionArgs args;
7934 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7935 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
7936
7937 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08007938 ASSERT_EQ(ACTION_POINTER_1_DOWN, args.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007939 ASSERT_EQ(size_t(2), args.getPointerCount());
Michael Wrightd02c5b62014-02-10 15:10:22 -08007940 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7941 x, y, 1.0f, size, touch, touch, tool, tool, 0, 0));
7942 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[1],
7943 x2, y2, 1.0f, size, touch, touch, tool, tool, 0, 0));
7944}
7945
7946TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_AreaCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007947 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007948 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007949 prepareAxes(POSITION | TOUCH | TOOL);
7950 addConfigurationProperty("touch.size.calibration", "area");
7951 addConfigurationProperty("touch.size.scale", "43");
7952 addConfigurationProperty("touch.size.bias", "3");
Arpit Singha8c236b2023-04-25 13:56:05 +00007953 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007954
7955 // These calculations are based on the input device calibration documentation.
7956 int32_t rawX = 100;
7957 int32_t rawY = 200;
7958 int32_t rawTouchMajor = 5;
7959 int32_t rawToolMajor = 8;
7960
7961 float x = toDisplayX(rawX);
7962 float y = toDisplayY(rawY);
7963 float size = float(rawTouchMajor) / RAW_TOUCH_MAX;
7964 float touch = sqrtf(rawTouchMajor) * 43.0f + 3.0f;
7965 float tool = sqrtf(rawToolMajor) * 43.0f + 3.0f;
7966
7967 processPosition(mapper, rawX, rawY);
7968 processTouchMajor(mapper, rawTouchMajor);
7969 processToolMajor(mapper, rawToolMajor);
7970 processMTSync(mapper);
7971 processSync(mapper);
7972
7973 NotifyMotionArgs args;
7974 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
7975 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
7976 x, y, 1.0f, size, touch, touch, tool, tool, 0, 0));
7977}
7978
7979TEST_F(MultiTouchInputMapperTest, Process_PressureAxis_AmplitudeCalibration) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08007980 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00007981 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007982 prepareAxes(POSITION | PRESSURE);
7983 addConfigurationProperty("touch.pressure.calibration", "amplitude");
7984 addConfigurationProperty("touch.pressure.scale", "0.01");
Arpit Singha8c236b2023-04-25 13:56:05 +00007985 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08007986
Michael Wrightaa449c92017-12-13 21:21:43 +00007987 InputDeviceInfo info;
Harry Cuttsd02ea102023-03-17 18:21:30 +00007988 mapper.populateDeviceInfo(info);
Michael Wrightaa449c92017-12-13 21:21:43 +00007989 ASSERT_NO_FATAL_FAILURE(assertMotionRange(info,
7990 AINPUT_MOTION_RANGE_PRESSURE, AINPUT_SOURCE_TOUCHSCREEN,
7991 0.0f, RAW_PRESSURE_MAX * 0.01, 0.0f, 0.0f));
7992
Michael Wrightd02c5b62014-02-10 15:10:22 -08007993 // These calculations are based on the input device calibration documentation.
7994 int32_t rawX = 100;
7995 int32_t rawY = 200;
7996 int32_t rawPressure = 60;
7997
7998 float x = toDisplayX(rawX);
7999 float y = toDisplayY(rawY);
8000 float pressure = float(rawPressure) * 0.01f;
8001
8002 processPosition(mapper, rawX, rawY);
8003 processPressure(mapper, rawPressure);
8004 processMTSync(mapper);
8005 processSync(mapper);
8006
8007 NotifyMotionArgs args;
8008 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8009 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
8010 x, y, pressure, 0, 0, 0, 0, 0, 0, 0));
8011}
8012
8013TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllButtons) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008014 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008015 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008016 prepareAxes(POSITION | ID | SLOT);
Arpit Singha8c236b2023-04-25 13:56:05 +00008017 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008018
8019 NotifyMotionArgs motionArgs;
8020 NotifyKeyArgs keyArgs;
8021
8022 processId(mapper, 1);
8023 processPosition(mapper, 100, 200);
8024 processSync(mapper);
8025 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8026 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8027 ASSERT_EQ(0, motionArgs.buttonState);
8028
8029 // press BTN_LEFT, release BTN_LEFT
8030 processKey(mapper, BTN_LEFT, 1);
8031 processSync(mapper);
8032 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8033 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
8034 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
8035
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008036 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8037 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8038 ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
8039
Michael Wrightd02c5b62014-02-10 15:10:22 -08008040 processKey(mapper, BTN_LEFT, 0);
8041 processSync(mapper);
8042 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008043 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008044 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008045
8046 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008047 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008048 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008049
8050 // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
8051 processKey(mapper, BTN_RIGHT, 1);
8052 processKey(mapper, BTN_MIDDLE, 1);
8053 processSync(mapper);
8054 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8055 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
8056 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
8057 motionArgs.buttonState);
8058
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008059 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8060 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8061 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
8062
8063 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8064 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8065 ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
8066 motionArgs.buttonState);
8067
Michael Wrightd02c5b62014-02-10 15:10:22 -08008068 processKey(mapper, BTN_RIGHT, 0);
8069 processSync(mapper);
8070 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008071 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008072 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008073
8074 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008075 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008076 ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008077
8078 processKey(mapper, BTN_MIDDLE, 0);
8079 processSync(mapper);
8080 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008081 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008082 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008083
8084 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008085 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008086 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008087
8088 // press BTN_BACK, release BTN_BACK
8089 processKey(mapper, BTN_BACK, 1);
8090 processSync(mapper);
8091 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8092 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8093 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008094
Michael Wrightd02c5b62014-02-10 15:10:22 -08008095 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008096 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008097 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
8098
8099 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8100 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8101 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008102
8103 processKey(mapper, BTN_BACK, 0);
8104 processSync(mapper);
8105 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008106 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008107 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008108
8109 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008110 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008111 ASSERT_EQ(0, motionArgs.buttonState);
8112
Michael Wrightd02c5b62014-02-10 15:10:22 -08008113 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8114 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8115 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
8116
8117 // press BTN_SIDE, release BTN_SIDE
8118 processKey(mapper, BTN_SIDE, 1);
8119 processSync(mapper);
8120 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8121 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8122 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008123
Michael Wrightd02c5b62014-02-10 15:10:22 -08008124 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008125 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008126 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
8127
8128 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8129 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8130 ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008131
8132 processKey(mapper, BTN_SIDE, 0);
8133 processSync(mapper);
8134 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008135 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008136 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008137
8138 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008139 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008140 ASSERT_EQ(0, motionArgs.buttonState);
8141
Michael Wrightd02c5b62014-02-10 15:10:22 -08008142 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8143 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8144 ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
8145
8146 // press BTN_FORWARD, release BTN_FORWARD
8147 processKey(mapper, BTN_FORWARD, 1);
8148 processSync(mapper);
8149 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8150 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8151 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008152
Michael Wrightd02c5b62014-02-10 15:10:22 -08008153 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008154 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008155 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
8156
8157 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8158 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8159 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008160
8161 processKey(mapper, BTN_FORWARD, 0);
8162 processSync(mapper);
8163 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008164 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008165 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008166
8167 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008168 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008169 ASSERT_EQ(0, motionArgs.buttonState);
8170
Michael Wrightd02c5b62014-02-10 15:10:22 -08008171 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8172 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8173 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
8174
8175 // press BTN_EXTRA, release BTN_EXTRA
8176 processKey(mapper, BTN_EXTRA, 1);
8177 processSync(mapper);
8178 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8179 ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
8180 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008181
Michael Wrightd02c5b62014-02-10 15:10:22 -08008182 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008183 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008184 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
8185
8186 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8187 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8188 ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008189
8190 processKey(mapper, BTN_EXTRA, 0);
8191 processSync(mapper);
8192 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008193 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008194 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008195
8196 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008197 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008198 ASSERT_EQ(0, motionArgs.buttonState);
8199
Michael Wrightd02c5b62014-02-10 15:10:22 -08008200 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
8201 ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
8202 ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
8203
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008204 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
8205
Michael Wrightd02c5b62014-02-10 15:10:22 -08008206 // press BTN_STYLUS, release BTN_STYLUS
8207 processKey(mapper, BTN_STYLUS, 1);
8208 processSync(mapper);
8209 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8210 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008211 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
8212
8213 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8214 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8215 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008216
8217 processKey(mapper, BTN_STYLUS, 0);
8218 processSync(mapper);
8219 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008220 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008221 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008222
8223 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008224 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008225 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008226
8227 // press BTN_STYLUS2, release BTN_STYLUS2
8228 processKey(mapper, BTN_STYLUS2, 1);
8229 processSync(mapper);
8230 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8231 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008232 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
8233
8234 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8235 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, motionArgs.action);
8236 ASSERT_EQ(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008237
8238 processKey(mapper, BTN_STYLUS2, 0);
8239 processSync(mapper);
8240 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008241 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, motionArgs.action);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008242 ASSERT_EQ(0, motionArgs.buttonState);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008243
8244 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Michael Wrightd02c5b62014-02-10 15:10:22 -08008245 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Vladislav Kaznacheevfb752582016-12-16 14:17:06 -08008246 ASSERT_EQ(0, motionArgs.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008247
8248 // release touch
8249 processId(mapper, -1);
8250 processSync(mapper);
8251 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8252 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8253 ASSERT_EQ(0, motionArgs.buttonState);
8254}
8255
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008256TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleMappedStylusButtons) {
8257 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008258 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008259 prepareAxes(POSITION | ID | SLOT);
Arpit Singha8c236b2023-04-25 13:56:05 +00008260 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +00008261
8262 mFakeEventHub->addKey(EVENTHUB_ID, BTN_A, 0, AKEYCODE_STYLUS_BUTTON_PRIMARY, 0);
8263 mFakeEventHub->addKey(EVENTHUB_ID, 0, 0xabcd, AKEYCODE_STYLUS_BUTTON_SECONDARY, 0);
8264
8265 // Touch down.
8266 processId(mapper, 1);
8267 processPosition(mapper, 100, 200);
8268 processSync(mapper);
8269 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8270 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithButtonState(0))));
8271
8272 // Press and release button mapped to the primary stylus button.
8273 processKey(mapper, BTN_A, 1);
8274 processSync(mapper);
8275 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8276 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
8277 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
8278 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8279 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
8280 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY))));
8281
8282 processKey(mapper, BTN_A, 0);
8283 processSync(mapper);
8284 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8285 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithButtonState(0))));
8286 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8287 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
8288
8289 // Press and release the HID usage mapped to the secondary stylus button.
8290 processHidUsage(mapper, 0xabcd, 1);
8291 processSync(mapper);
8292 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8293 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
8294 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY))));
8295 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8296 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
8297 WithButtonState(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY))));
8298
8299 processHidUsage(mapper, 0xabcd, 0);
8300 processSync(mapper);
8301 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8302 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE), WithButtonState(0))));
8303 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8304 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithButtonState(0))));
8305
8306 // Release touch.
8307 processId(mapper, -1);
8308 processSync(mapper);
8309 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8310 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithButtonState(0))));
8311}
8312
Michael Wrightd02c5b62014-02-10 15:10:22 -08008313TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008314 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008315 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008316 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00008317 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008318
8319 NotifyMotionArgs motionArgs;
8320
8321 // default tool type is finger
8322 processId(mapper, 1);
8323 processPosition(mapper, 100, 200);
8324 processSync(mapper);
8325 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8326 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008327 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008328
8329 // eraser
8330 processKey(mapper, BTN_TOOL_RUBBER, 1);
8331 processSync(mapper);
8332 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8333 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008334 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008335
8336 // stylus
8337 processKey(mapper, BTN_TOOL_RUBBER, 0);
8338 processKey(mapper, BTN_TOOL_PEN, 1);
8339 processSync(mapper);
8340 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8341 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008342 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008343
8344 // brush
8345 processKey(mapper, BTN_TOOL_PEN, 0);
8346 processKey(mapper, BTN_TOOL_BRUSH, 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::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008351
8352 // pencil
8353 processKey(mapper, BTN_TOOL_BRUSH, 0);
8354 processKey(mapper, BTN_TOOL_PENCIL, 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
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08008360 // air-brush
Michael Wrightd02c5b62014-02-10 15:10:22 -08008361 processKey(mapper, BTN_TOOL_PENCIL, 0);
8362 processKey(mapper, BTN_TOOL_AIRBRUSH, 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 // mouse
8369 processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
8370 processKey(mapper, BTN_TOOL_MOUSE, 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::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008375
8376 // lens
8377 processKey(mapper, BTN_TOOL_MOUSE, 0);
8378 processKey(mapper, BTN_TOOL_LENS, 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::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008383
8384 // double-tap
8385 processKey(mapper, BTN_TOOL_LENS, 0);
8386 processKey(mapper, BTN_TOOL_DOUBLETAP, 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::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008391
8392 // triple-tap
8393 processKey(mapper, BTN_TOOL_DOUBLETAP, 0);
8394 processKey(mapper, BTN_TOOL_TRIPLETAP, 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::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008399
8400 // quad-tap
8401 processKey(mapper, BTN_TOOL_TRIPLETAP, 0);
8402 processKey(mapper, BTN_TOOL_QUADTAP, 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 // finger
8409 processKey(mapper, BTN_TOOL_QUADTAP, 0);
8410 processKey(mapper, BTN_TOOL_FINGER, 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 // stylus trumps finger
8417 processKey(mapper, BTN_TOOL_PEN, 1);
8418 processSync(mapper);
8419 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8420 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008421 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008422
8423 // eraser trumps stylus
8424 processKey(mapper, BTN_TOOL_RUBBER, 1);
8425 processSync(mapper);
8426 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8427 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008428 ASSERT_EQ(ToolType::ERASER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008429
8430 // mouse trumps eraser
8431 processKey(mapper, BTN_TOOL_MOUSE, 1);
8432 processSync(mapper);
8433 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8434 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008435 ASSERT_EQ(ToolType::MOUSE, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008436
8437 // MT tool type trumps BTN tool types: MT_TOOL_FINGER
8438 processToolType(mapper, MT_TOOL_FINGER); // this is the first time we send MT_TOOL_TYPE
8439 processSync(mapper);
8440 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8441 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008442 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008443
8444 // MT tool type trumps BTN tool types: MT_TOOL_PEN
8445 processToolType(mapper, MT_TOOL_PEN);
8446 processSync(mapper);
8447 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8448 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008449 ASSERT_EQ(ToolType::STYLUS, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008450
8451 // back to default tool type
8452 processToolType(mapper, -1); // use a deliberately undefined tool type, for testing
8453 processKey(mapper, BTN_TOOL_MOUSE, 0);
8454 processKey(mapper, BTN_TOOL_RUBBER, 0);
8455 processKey(mapper, BTN_TOOL_PEN, 0);
8456 processKey(mapper, BTN_TOOL_FINGER, 0);
8457 processSync(mapper);
8458 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8459 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008460 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008461}
8462
8463TEST_F(MultiTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008464 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008465 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008466 prepareAxes(POSITION | ID | SLOT);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008467 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00008468 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008469
8470 NotifyMotionArgs motionArgs;
8471
8472 // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0
8473 processId(mapper, 1);
8474 processPosition(mapper, 100, 200);
8475 processSync(mapper);
8476 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8477 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8478 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8479 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8480
8481 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8482 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8483 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8484 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8485
8486 // move a little
8487 processPosition(mapper, 150, 250);
8488 processSync(mapper);
8489 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8490 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8491 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8492 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8493
8494 // down when BTN_TOUCH is pressed, pressure defaults to 1
8495 processKey(mapper, BTN_TOUCH, 1);
8496 processSync(mapper);
8497 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8498 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8499 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8500 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8501
8502 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8503 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8504 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8505 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8506
8507 // up when BTN_TOUCH is released, hover restored
8508 processKey(mapper, BTN_TOUCH, 0);
8509 processSync(mapper);
8510 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8511 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8512 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8513 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8514
8515 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8516 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8517 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8518 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8519
8520 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8521 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8522 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8523 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8524
8525 // exit hover when pointer goes away
8526 processId(mapper, -1);
8527 processSync(mapper);
8528 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8529 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8530 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8531 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8532}
8533
8534TEST_F(MultiTouchInputMapperTest, Process_WhenAbsMTPressureIsPresent_HoversIfItsValueIsZero) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08008535 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008536 prepareDisplay(ui::ROTATION_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08008537 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00008538 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Michael Wrightd02c5b62014-02-10 15:10:22 -08008539
8540 NotifyMotionArgs motionArgs;
8541
8542 // initially hovering because pressure is 0
8543 processId(mapper, 1);
8544 processPosition(mapper, 100, 200);
8545 processPressure(mapper, 0);
8546 processSync(mapper);
8547 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8548 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8549 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8550 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8551
8552 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8553 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8554 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8555 toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
8556
8557 // move a little
8558 processPosition(mapper, 150, 250);
8559 processSync(mapper);
8560 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8561 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8562 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8563 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8564
8565 // down when pressure becomes non-zero
8566 processPressure(mapper, RAW_PRESSURE_MAX);
8567 processSync(mapper);
8568 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8569 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8570 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8571 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8572
8573 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8574 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8575 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8576 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8577
8578 // up when pressure becomes 0, hover restored
8579 processPressure(mapper, 0);
8580 processSync(mapper);
8581 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8582 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
8583 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8584 toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
8585
8586 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8587 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
8588 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8589 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8590
8591 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8592 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
8593 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8594 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8595
8596 // exit hover when pointer goes away
8597 processId(mapper, -1);
8598 processSync(mapper);
8599 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8600 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
8601 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
8602 toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
8603}
8604
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008605/**
8606 * Set the input device port <--> display port associations, and check that the
8607 * events are routed to the display that matches the display port.
8608 * This can be checked by looking at the displayId of the resulting NotifyMotionArgs.
8609 */
8610TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayPort) {
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008611 const std::string usb2 = "USB2";
8612 const uint8_t hdmi1 = 0;
8613 const uint8_t hdmi2 = 1;
8614 const std::string secondaryUniqueId = "uniqueId2";
Michael Wrightfe3de7d2020-07-02 19:05:30 +01008615 constexpr ViewportType type = ViewportType::EXTERNAL;
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008616
8617 addConfigurationProperty("touch.deviceType", "touchScreen");
8618 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008619 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008620
8621 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
8622 mFakePolicy->addInputPortAssociation(usb2, hdmi2);
8623
8624 // We are intentionally not adding the viewport for display 1 yet. Since the port association
8625 // for this input device is specified, and the matching viewport is not present,
8626 // the input device should be disabled (at the mapper level).
8627
8628 // Add viewport for display 2 on hdmi2
8629 prepareSecondaryDisplay(type, hdmi2);
8630 // Send a touch event
8631 processPosition(mapper, 100, 100);
8632 processSync(mapper);
8633 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
8634
8635 // Add viewport for display 1 on hdmi1
Michael Wrighta9cf4192022-12-01 23:46:39 +00008636 prepareDisplay(ui::ROTATION_0, hdmi1);
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07008637 // Send a touch event again
8638 processPosition(mapper, 100, 100);
8639 processSync(mapper);
8640
8641 NotifyMotionArgs args;
8642 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8643 ASSERT_EQ(DISPLAY_ID, args.displayId);
8644}
Michael Wrightd02c5b62014-02-10 15:10:22 -08008645
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008646TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayUniqueId) {
8647 addConfigurationProperty("touch.deviceType", "touchScreen");
8648 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008649 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008650
8651 mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID);
8652
Michael Wrighta9cf4192022-12-01 23:46:39 +00008653 prepareDisplay(ui::ROTATION_0);
8654 prepareVirtualDisplay(ui::ROTATION_0);
Arthur Hung6d5b4b22022-01-21 07:21:10 +00008655
8656 // Send a touch event
8657 processPosition(mapper, 100, 100);
8658 processSync(mapper);
8659
8660 NotifyMotionArgs args;
8661 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8662 ASSERT_EQ(VIRTUAL_DISPLAY_ID, args.displayId);
8663}
8664
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008665TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
Michael Wrightfe3de7d2020-07-02 19:05:30 +01008666 prepareSecondaryDisplay(ViewportType::EXTERNAL);
Garfield Tan888a6a42020-01-09 11:39:16 -08008667
Michael Wrighta9cf4192022-12-01 23:46:39 +00008668 prepareDisplay(ui::ROTATION_0);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008669 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008670 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008671
Josep del Río2d8c79a2023-01-23 19:33:50 +00008672 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008673
8674 NotifyMotionArgs motionArgs;
8675 processPosition(mapper, 100, 100);
8676 processSync(mapper);
8677
8678 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8679 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008680 ASSERT_EQ(ui::LogicalDisplayId::INVALID, motionArgs.displayId);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08008681}
8682
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008683/**
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008684 * Ensure that the readTime is set to the SYN_REPORT value when processing touch events.
8685 */
8686TEST_F(MultiTouchInputMapperTest, Process_SendsReadTime) {
8687 addConfigurationProperty("touch.deviceType", "touchScreen");
8688 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008689 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008690
Michael Wrighta9cf4192022-12-01 23:46:39 +00008691 prepareDisplay(ui::ROTATION_0);
Harry Cutts33476232023-01-30 19:57:29 +00008692 process(mapper, 10, /*readTime=*/11, EV_ABS, ABS_MT_TRACKING_ID, 1);
8693 process(mapper, 15, /*readTime=*/16, EV_ABS, ABS_MT_POSITION_X, 100);
8694 process(mapper, 20, /*readTime=*/21, EV_ABS, ABS_MT_POSITION_Y, 100);
8695 process(mapper, 25, /*readTime=*/26, EV_SYN, SYN_REPORT, 0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008696
8697 NotifyMotionArgs args;
8698 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8699 ASSERT_EQ(26, args.readTime);
8700
Harry Cutts33476232023-01-30 19:57:29 +00008701 process(mapper, 30, /*readTime=*/31, EV_ABS, ABS_MT_POSITION_X, 110);
8702 process(mapper, 30, /*readTime=*/32, EV_ABS, ABS_MT_POSITION_Y, 220);
8703 process(mapper, 30, /*readTime=*/33, EV_SYN, SYN_REPORT, 0);
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00008704
8705 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
8706 ASSERT_EQ(33, args.readTime);
8707}
8708
8709/**
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008710 * When the viewport is not active (isActive=false), the touch mapper should be disabled and the
8711 * events should not be delivered to the listener.
8712 */
8713TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreDropped) {
8714 addConfigurationProperty("touch.deviceType", "touchScreen");
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008715 // Don't set touch.enableForInactiveViewport to verify the default behavior.
Michael Wrighta9cf4192022-12-01 23:46:39 +00008716 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008717 /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008718 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008719 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008720 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou6f778462020-12-09 23:39:07 +00008721
8722 NotifyMotionArgs motionArgs;
8723 processPosition(mapper, 100, 100);
8724 processSync(mapper);
8725
8726 mFakeListener->assertNotifyMotionWasNotCalled();
8727}
8728
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008729/**
8730 * When the viewport is not active (isActive=false) and touch.enableForInactiveViewport is true,
8731 * the touch mapper can process the events and the events can be delivered to the listener.
8732 */
8733TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreProcessed) {
8734 addConfigurationProperty("touch.deviceType", "touchScreen");
8735 addConfigurationProperty("touch.enableForInactiveViewport", "1");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008736 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008737 /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008738 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008739 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008740 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008741
8742 NotifyMotionArgs motionArgs;
8743 processPosition(mapper, 100, 100);
8744 processSync(mapper);
8745
8746 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8747 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8748}
8749
Josh Thielene986aed2023-06-01 14:17:30 +00008750/**
8751 * When the viewport is deactivated (isActive transitions from true to false),
8752 * and touch.enableForInactiveViewport is false, touches prior to the transition
8753 * should be cancelled.
8754 */
Garfield Tanc734e4f2021-01-15 20:01:39 -08008755TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_AbortTouches) {
8756 addConfigurationProperty("touch.deviceType", "touchScreen");
Yuncheol Heo50c19b12022-11-02 20:33:08 -07008757 addConfigurationProperty("touch.enableForInactiveViewport", "0");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008758 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
Harry Cutts33476232023-01-30 19:57:29 +00008759 /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008760 std::optional<DisplayViewport> optionalDisplayViewport =
8761 mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
8762 ASSERT_TRUE(optionalDisplayViewport.has_value());
8763 DisplayViewport displayViewport = *optionalDisplayViewport;
8764
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008765 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008766 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00008767 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Garfield Tanc734e4f2021-01-15 20:01:39 -08008768
8769 // Finger down
8770 int32_t x = 100, y = 100;
8771 processPosition(mapper, x, y);
8772 processSync(mapper);
8773
8774 NotifyMotionArgs motionArgs;
8775 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8776 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
8777
8778 // Deactivate display viewport
8779 displayViewport.isActive = false;
8780 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008781 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008782
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008783 // The ongoing touch should be canceled immediately
8784 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8785 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
8786
8787 // Finger move is ignored
Garfield Tanc734e4f2021-01-15 20:01:39 -08008788 x += 10, y += 10;
8789 processPosition(mapper, x, y);
8790 processSync(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008791 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
Garfield Tanc734e4f2021-01-15 20:01:39 -08008792
8793 // Reactivate display viewport
8794 displayViewport.isActive = true;
8795 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
Prabir Pradhan4bf6d452023-04-18 21:26:56 +00008796 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008797
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008798 // Finger move again starts new gesture
Garfield Tanc734e4f2021-01-15 20:01:39 -08008799 x += 10, y += 10;
8800 processPosition(mapper, x, y);
8801 processSync(mapper);
Prabir Pradhanc0bdeef2022-08-05 22:32:11 +00008802 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8803 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Garfield Tanc734e4f2021-01-15 20:01:39 -08008804}
8805
Josh Thielene986aed2023-06-01 14:17:30 +00008806/**
8807 * When the viewport is deactivated (isActive transitions from true to false),
8808 * and touch.enableForInactiveViewport is true, touches prior to the transition
8809 * should not be cancelled.
8810 */
8811TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_TouchesNotAborted) {
8812 addConfigurationProperty("touch.deviceType", "touchScreen");
8813 addConfigurationProperty("touch.enableForInactiveViewport", "1");
8814 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
8815 /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
8816 std::optional<DisplayViewport> optionalDisplayViewport =
8817 mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
8818 ASSERT_TRUE(optionalDisplayViewport.has_value());
8819 DisplayViewport displayViewport = *optionalDisplayViewport;
8820
8821 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8822 prepareAxes(POSITION);
8823 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
8824
8825 // Finger down
8826 int32_t x = 100, y = 100;
8827 processPosition(mapper, x, y);
8828 processSync(mapper);
8829 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8830 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
8831
8832 // Deactivate display viewport
8833 displayViewport.isActive = false;
8834 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
8835 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8836
8837 // The ongoing touch should not be canceled
8838 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
8839
8840 // Finger move is not ignored
8841 x += 10, y += 10;
8842 processPosition(mapper, x, y);
8843 processSync(mapper);
8844 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8845 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
8846
8847 // Reactivate display viewport
8848 displayViewport.isActive = true;
8849 ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
8850 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
8851
8852 // Finger move continues and does not start new gesture
8853 x += 10, y += 10;
8854 processPosition(mapper, x, y);
8855 processSync(mapper);
8856 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
8857 WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
8858}
8859
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008860TEST_F(MultiTouchInputMapperTest, VideoFrames_ReceivedByListener) {
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008861 prepareAxes(POSITION);
8862 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00008863 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00008864 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008865
8866 NotifyMotionArgs motionArgs;
8867 // Unrotated video frame
8868 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8869 std::vector<TouchVideoFrame> frames{frame};
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008870 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou6b76bdf2019-02-15 20:01:35 -06008871 processPosition(mapper, 100, 200);
8872 processSync(mapper);
8873 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8874 ASSERT_EQ(frames, motionArgs.videoFrames);
8875
8876 // Subsequent touch events should not have any videoframes
8877 // This is implemented separately in FakeEventHub,
8878 // but that should match the behaviour of TouchVideoDevice.
8879 processPosition(mapper, 200, 200);
8880 processSync(mapper);
8881 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8882 ASSERT_EQ(std::vector<TouchVideoFrame>(), motionArgs.videoFrames);
8883}
8884
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008885TEST_F(MultiTouchInputMapperTest, VideoFrames_AreNotRotated) {
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008886 prepareAxes(POSITION);
8887 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00008888 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008889 // Unrotated video frame
8890 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8891 NotifyMotionArgs motionArgs;
8892
8893 // Test all 4 orientations
Michael Wrighta9cf4192022-12-01 23:46:39 +00008894 for (ui::Rotation orientation : ftl::enum_range<ui::Rotation>()) {
Harry Cuttsc57cd3c2024-04-24 13:52:55 +00008895 SCOPED_TRACE(StringPrintf("Orientation %s", ftl::enum_string(orientation).c_str()));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008896 clearViewports();
8897 prepareDisplay(orientation);
8898 std::vector<TouchVideoFrame> frames{frame};
8899 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
8900 processPosition(mapper, 100, 200);
8901 processSync(mapper);
8902 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8903 ASSERT_EQ(frames, motionArgs.videoFrames);
8904 }
8905}
8906
8907TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_AreRotated) {
8908 prepareAxes(POSITION);
8909 addConfigurationProperty("touch.deviceType", "touchScreen");
8910 // Since InputReader works in the un-rotated coordinate space, only devices that are not
8911 // orientation-aware are affected by display rotation.
8912 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00008913 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008914 // Unrotated video frame
8915 TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8916 NotifyMotionArgs motionArgs;
8917
8918 // Test all 4 orientations
Michael Wrighta9cf4192022-12-01 23:46:39 +00008919 for (ui::Rotation orientation : ftl::enum_range<ui::Rotation>()) {
Harry Cuttsc57cd3c2024-04-24 13:52:55 +00008920 SCOPED_TRACE(StringPrintf("Orientation %s", ftl::enum_string(orientation).c_str()));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008921 clearViewports();
8922 prepareDisplay(orientation);
8923 std::vector<TouchVideoFrame> frames{frame};
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008924 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008925 processPosition(mapper, 100, 200);
8926 processSync(mapper);
8927 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008928 // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction
8929 // compared to the display. This is so that when the window transform (which contains the
8930 // display rotation) is applied later by InputDispatcher, the coordinates end up in the
8931 // window's coordinate space.
8932 frames[0].rotate(getInverseRotation(orientation));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008933 ASSERT_EQ(frames, motionArgs.videoFrames);
lilinnan687e58f2022-07-19 16:00:50 +08008934
8935 // Release finger.
8936 processSync(mapper);
8937 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008938 }
8939}
8940
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008941TEST_F(MultiTouchInputMapperTest, VideoFrames_MultipleFramesAreNotRotated) {
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008942 prepareAxes(POSITION);
8943 addConfigurationProperty("touch.deviceType", "touchScreen");
Arpit Singha8c236b2023-04-25 13:56:05 +00008944 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008945 // Unrotated video frames. There's no rule that they must all have the same dimensions,
8946 // so mix these.
8947 TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8948 TouchVideoFrame frame2(3, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {1, 3});
8949 TouchVideoFrame frame3(2, 2, {10, 20, 10, 0}, {1, 4});
8950 std::vector<TouchVideoFrame> frames{frame1, frame2, frame3};
8951 NotifyMotionArgs motionArgs;
8952
Michael Wrighta9cf4192022-12-01 23:46:39 +00008953 prepareDisplay(ui::ROTATION_90);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08008954 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008955 processPosition(mapper, 100, 200);
8956 processSync(mapper);
8957 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008958 ASSERT_EQ(frames, motionArgs.videoFrames);
8959}
8960
8961TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_MultipleFramesAreRotated) {
8962 prepareAxes(POSITION);
8963 addConfigurationProperty("touch.deviceType", "touchScreen");
8964 // Since InputReader works in the un-rotated coordinate space, only devices that are not
8965 // orientation-aware are affected by display rotation.
8966 addConfigurationProperty("touch.orientationAware", "0");
Arpit Singha8c236b2023-04-25 13:56:05 +00008967 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008968 // Unrotated video frames. There's no rule that they must all have the same dimensions,
8969 // so mix these.
8970 TouchVideoFrame frame1(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
8971 TouchVideoFrame frame2(3, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {1, 3});
8972 TouchVideoFrame frame3(2, 2, {10, 20, 10, 0}, {1, 4});
8973 std::vector<TouchVideoFrame> frames{frame1, frame2, frame3};
8974 NotifyMotionArgs motionArgs;
8975
Michael Wrighta9cf4192022-12-01 23:46:39 +00008976 prepareDisplay(ui::ROTATION_90);
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008977 mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
8978 processPosition(mapper, 100, 200);
8979 processSync(mapper);
8980 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
8981 std::for_each(frames.begin(), frames.end(), [](TouchVideoFrame& frame) {
8982 // We expect the raw coordinates of the MotionEvent to be rotated in the inverse direction
8983 // compared to the display. This is so that when the window transform (which contains the
8984 // display rotation) is applied later by InputDispatcher, the coordinates end up in the
8985 // window's coordinate space.
Michael Wrighta9cf4192022-12-01 23:46:39 +00008986 frame.rotate(getInverseRotation(ui::ROTATION_90));
Prabir Pradhanc14266f2021-05-12 15:56:24 -07008987 });
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06008988 ASSERT_EQ(frames, motionArgs.videoFrames);
8989}
8990
Arthur Hung9da14732019-09-02 16:16:58 +08008991/**
8992 * If we had defined port associations, but the viewport is not ready, the touch device would be
8993 * expected to be disabled, and it should be enabled after the viewport has found.
8994 */
8995TEST_F(MultiTouchInputMapperTest, Configure_EnabledForAssociatedDisplay) {
Arthur Hung9da14732019-09-02 16:16:58 +08008996 constexpr uint8_t hdmi2 = 1;
8997 const std::string secondaryUniqueId = "uniqueId2";
Michael Wrightfe3de7d2020-07-02 19:05:30 +01008998 constexpr ViewportType type = ViewportType::EXTERNAL;
Arthur Hung9da14732019-09-02 16:16:58 +08008999
9000 mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi2);
9001
9002 addConfigurationProperty("touch.deviceType", "touchScreen");
9003 prepareAxes(POSITION);
Arpit Singha8c236b2023-04-25 13:56:05 +00009004 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung9da14732019-09-02 16:16:58 +08009005
9006 ASSERT_EQ(mDevice->isEnabled(), false);
9007
9008 // Add display on hdmi2, the device should be enabled and can receive touch event.
9009 prepareSecondaryDisplay(type, hdmi2);
9010 ASSERT_EQ(mDevice->isEnabled(), true);
9011
9012 // Send a touch event.
9013 processPosition(mapper, 100, 100);
9014 processSync(mapper);
9015
9016 NotifyMotionArgs args;
9017 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9018 ASSERT_EQ(SECONDARY_DISPLAY_ID, args.displayId);
9019}
9020
Arthur Hung421eb1c2020-01-16 00:09:42 +08009021TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleSingleTouch) {
Arthur Hung421eb1c2020-01-16 00:09:42 +08009022 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009023 prepareDisplay(ui::ROTATION_0);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009024 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009025 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung421eb1c2020-01-16 00:09:42 +08009026
9027 NotifyMotionArgs motionArgs;
9028
9029 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
9030 // finger down
9031 processId(mapper, 1);
9032 processPosition(mapper, x1, y1);
9033 processSync(mapper);
9034 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9035 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009036 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009037
9038 // finger move
9039 processId(mapper, 1);
9040 processPosition(mapper, x2, y2);
9041 processSync(mapper);
9042 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9043 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009044 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009045
9046 // finger up.
9047 processId(mapper, -1);
9048 processSync(mapper);
9049 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9050 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009051 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009052
9053 // new finger down
9054 processId(mapper, 1);
9055 processPosition(mapper, x3, y3);
9056 processSync(mapper);
9057 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9058 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009059 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009060}
9061
9062/**
arthurhungcc7f9802020-04-30 17:55:40 +08009063 * Test single touch should be canceled when received the MT_TOOL_PALM event, and the following
9064 * MOVE and UP events should be ignored.
Arthur Hung421eb1c2020-01-16 00:09:42 +08009065 */
arthurhungcc7f9802020-04-30 17:55:40 +08009066TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_SinglePointer) {
Arthur Hung421eb1c2020-01-16 00:09:42 +08009067 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009068 prepareDisplay(ui::ROTATION_0);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009069 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009070 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung421eb1c2020-01-16 00:09:42 +08009071
9072 NotifyMotionArgs motionArgs;
9073
9074 // default tool type is finger
9075 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
arthurhungcc7f9802020-04-30 17:55:40 +08009076 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009077 processPosition(mapper, x1, y1);
9078 processSync(mapper);
9079 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9080 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009081 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009082
9083 // Tool changed to MT_TOOL_PALM expect sending the cancel event.
9084 processToolType(mapper, MT_TOOL_PALM);
9085 processSync(mapper);
9086 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9087 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9088
9089 // Ignore the following MOVE and UP events if had detect a palm event.
arthurhungcc7f9802020-04-30 17:55:40 +08009090 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009091 processPosition(mapper, x2, y2);
9092 processSync(mapper);
9093 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9094
9095 // finger up.
arthurhungcc7f9802020-04-30 17:55:40 +08009096 processId(mapper, INVALID_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009097 processSync(mapper);
9098 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9099
9100 // new finger down
arthurhungcc7f9802020-04-30 17:55:40 +08009101 processId(mapper, FIRST_TRACKING_ID);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009102 processToolType(mapper, MT_TOOL_FINGER);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009103 processPosition(mapper, x3, y3);
9104 processSync(mapper);
9105 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9106 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009107 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Arthur Hung421eb1c2020-01-16 00:09:42 +08009108}
9109
arthurhungbf89a482020-04-17 17:37:55 +08009110/**
arthurhungcc7f9802020-04-30 17:55:40 +08009111 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event from some finger,
9112 * and the rest active fingers could still be allowed to receive the events
arthurhungbf89a482020-04-17 17:37:55 +08009113 */
arthurhungcc7f9802020-04-30 17:55:40 +08009114TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_TwoPointers) {
arthurhungbf89a482020-04-17 17:37:55 +08009115 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009116 prepareDisplay(ui::ROTATION_0);
arthurhungbf89a482020-04-17 17:37:55 +08009117 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009118 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungbf89a482020-04-17 17:37:55 +08009119
9120 NotifyMotionArgs motionArgs;
9121
9122 // default tool type is finger
arthurhungcc7f9802020-04-30 17:55:40 +08009123 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220;
9124 processId(mapper, FIRST_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009125 processPosition(mapper, x1, y1);
9126 processSync(mapper);
9127 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9128 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009129 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungbf89a482020-04-17 17:37:55 +08009130
9131 // Second finger down.
arthurhungcc7f9802020-04-30 17:55:40 +08009132 processSlot(mapper, SECOND_SLOT);
9133 processId(mapper, SECOND_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009134 processPosition(mapper, x2, y2);
arthurhungcc7f9802020-04-30 17:55:40 +08009135 processSync(mapper);
9136 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009137 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009138 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[1].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009139
9140 // If the tool type of the first finger changes to MT_TOOL_PALM,
9141 // we expect to receive ACTION_POINTER_UP with cancel flag.
9142 processSlot(mapper, FIRST_SLOT);
9143 processId(mapper, FIRST_TRACKING_ID);
9144 processToolType(mapper, MT_TOOL_PALM);
9145 processSync(mapper);
9146 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009147 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009148 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9149
9150 // The following MOVE events of second finger should be processed.
9151 processSlot(mapper, SECOND_SLOT);
9152 processId(mapper, SECOND_TRACKING_ID);
9153 processPosition(mapper, x2 + 1, y2 + 1);
9154 processSync(mapper);
9155 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9156 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009157 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009158
9159 // First finger up. It used to be in palm mode, and we already generated ACTION_POINTER_UP for
9160 // it. Second finger receive move.
9161 processSlot(mapper, FIRST_SLOT);
9162 processId(mapper, INVALID_TRACKING_ID);
9163 processSync(mapper);
9164 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9165 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009166 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009167
9168 // Second finger keeps moving.
9169 processSlot(mapper, SECOND_SLOT);
9170 processId(mapper, SECOND_TRACKING_ID);
9171 processPosition(mapper, x2 + 2, y2 + 2);
9172 processSync(mapper);
9173 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9174 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009175 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009176
9177 // Second finger up.
9178 processId(mapper, INVALID_TRACKING_ID);
9179 processSync(mapper);
9180 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9181 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9182 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9183}
9184
9185/**
9186 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event, if only 1 finger
9187 * is active, it should send CANCEL after receiving the MT_TOOL_PALM event.
9188 */
9189TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_ShouldCancelWhenAllTouchIsPalm) {
9190 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009191 prepareDisplay(ui::ROTATION_0);
arthurhungcc7f9802020-04-30 17:55:40 +08009192 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009193 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungcc7f9802020-04-30 17:55:40 +08009194
9195 NotifyMotionArgs motionArgs;
9196
9197 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
9198 // First finger down.
9199 processId(mapper, FIRST_TRACKING_ID);
9200 processPosition(mapper, x1, y1);
9201 processSync(mapper);
9202 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9203 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009204 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009205
9206 // Second finger down.
9207 processSlot(mapper, SECOND_SLOT);
9208 processId(mapper, SECOND_TRACKING_ID);
9209 processPosition(mapper, x2, y2);
arthurhungbf89a482020-04-17 17:37:55 +08009210 processSync(mapper);
9211 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009212 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009213 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungbf89a482020-04-17 17:37:55 +08009214
arthurhungcc7f9802020-04-30 17:55:40 +08009215 // If the tool type of the first finger changes to MT_TOOL_PALM,
9216 // we expect to receive ACTION_POINTER_UP with cancel flag.
9217 processSlot(mapper, FIRST_SLOT);
9218 processId(mapper, FIRST_TRACKING_ID);
9219 processToolType(mapper, MT_TOOL_PALM);
9220 processSync(mapper);
9221 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009222 ASSERT_EQ(ACTION_POINTER_0_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009223 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9224
9225 // Second finger keeps moving.
9226 processSlot(mapper, SECOND_SLOT);
9227 processId(mapper, SECOND_TRACKING_ID);
9228 processPosition(mapper, x2 + 1, y2 + 1);
9229 processSync(mapper);
9230 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9231 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9232
9233 // second finger becomes palm, receive cancel due to only 1 finger is active.
9234 processId(mapper, SECOND_TRACKING_ID);
arthurhungbf89a482020-04-17 17:37:55 +08009235 processToolType(mapper, MT_TOOL_PALM);
9236 processSync(mapper);
9237 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9238 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9239
arthurhungcc7f9802020-04-30 17:55:40 +08009240 // third finger down.
9241 processSlot(mapper, THIRD_SLOT);
9242 processId(mapper, THIRD_TRACKING_ID);
9243 processToolType(mapper, MT_TOOL_FINGER);
arthurhungbf89a482020-04-17 17:37:55 +08009244 processPosition(mapper, x3, y3);
9245 processSync(mapper);
arthurhungbf89a482020-04-17 17:37:55 +08009246 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9247 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009248 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009249 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009250
9251 // third finger move
9252 processId(mapper, THIRD_TRACKING_ID);
9253 processPosition(mapper, x3 + 1, y3 + 1);
9254 processSync(mapper);
9255 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9256 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9257
9258 // first finger up, third finger receive move.
9259 processSlot(mapper, FIRST_SLOT);
9260 processId(mapper, INVALID_TRACKING_ID);
9261 processSync(mapper);
9262 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9263 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009264 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009265
9266 // second finger up, third finger receive move.
9267 processSlot(mapper, SECOND_SLOT);
9268 processId(mapper, INVALID_TRACKING_ID);
9269 processSync(mapper);
9270 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9271 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009272 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009273
9274 // third finger up.
9275 processSlot(mapper, THIRD_SLOT);
9276 processId(mapper, INVALID_TRACKING_ID);
9277 processSync(mapper);
9278 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9279 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9280 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9281}
9282
9283/**
9284 * Test multi-touch should sent POINTER_UP when received the MT_TOOL_PALM event from some finger,
9285 * and the active finger could still be allowed to receive the events
9286 */
9287TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_KeepFirstPointer) {
9288 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009289 prepareDisplay(ui::ROTATION_0);
arthurhungcc7f9802020-04-30 17:55:40 +08009290 prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009291 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
arthurhungcc7f9802020-04-30 17:55:40 +08009292
9293 NotifyMotionArgs motionArgs;
9294
9295 // default tool type is finger
9296 constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220;
9297 processId(mapper, FIRST_TRACKING_ID);
9298 processPosition(mapper, x1, y1);
9299 processSync(mapper);
9300 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9301 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009302 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009303
9304 // Second finger down.
9305 processSlot(mapper, SECOND_SLOT);
9306 processId(mapper, SECOND_TRACKING_ID);
9307 processPosition(mapper, x2, y2);
9308 processSync(mapper);
9309 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009310 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009311 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
arthurhungcc7f9802020-04-30 17:55:40 +08009312
9313 // If the tool type of the second finger changes to MT_TOOL_PALM,
9314 // we expect to receive ACTION_POINTER_UP with cancel flag.
9315 processId(mapper, SECOND_TRACKING_ID);
9316 processToolType(mapper, MT_TOOL_PALM);
9317 processSync(mapper);
9318 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009319 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
arthurhungcc7f9802020-04-30 17:55:40 +08009320 ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
9321
9322 // The following MOVE event should be processed.
9323 processSlot(mapper, FIRST_SLOT);
9324 processId(mapper, FIRST_TRACKING_ID);
9325 processPosition(mapper, x1 + 1, y1 + 1);
9326 processSync(mapper);
9327 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9328 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009329 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
arthurhungcc7f9802020-04-30 17:55:40 +08009330
9331 // second finger up.
9332 processSlot(mapper, SECOND_SLOT);
9333 processId(mapper, INVALID_TRACKING_ID);
9334 processSync(mapper);
9335 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9336 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9337
9338 // first finger keep moving
9339 processSlot(mapper, FIRST_SLOT);
9340 processId(mapper, FIRST_TRACKING_ID);
9341 processPosition(mapper, x1 + 2, y1 + 2);
9342 processSync(mapper);
9343 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9344 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
9345
9346 // first finger up.
9347 processId(mapper, INVALID_TRACKING_ID);
9348 processSync(mapper);
9349 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9350 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
9351 ASSERT_NE(AMOTION_EVENT_FLAG_CANCELED, motionArgs.flags);
arthurhungbf89a482020-04-17 17:37:55 +08009352}
9353
Arthur Hung9ad18942021-06-19 02:04:46 +00009354/**
9355 * Test multi-touch should sent ACTION_POINTER_UP/ACTION_UP when received the INVALID_TRACKING_ID,
9356 * to prevent the driver side may send unexpected data after set tracking id as INVALID_TRACKING_ID
9357 * cause slot be valid again.
9358 */
9359TEST_F(MultiTouchInputMapperTest, Process_MultiTouch_WithInvalidTrackingId) {
9360 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009361 prepareDisplay(ui::ROTATION_0);
Arthur Hung9ad18942021-06-19 02:04:46 +00009362 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009363 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Arthur Hung9ad18942021-06-19 02:04:46 +00009364
9365 NotifyMotionArgs motionArgs;
9366
9367 constexpr int32_t x1 = 100, y1 = 200, x2 = 0, y2 = 0;
9368 // First finger down.
9369 processId(mapper, FIRST_TRACKING_ID);
9370 processPosition(mapper, x1, y1);
9371 processPressure(mapper, RAW_PRESSURE_MAX);
9372 processSync(mapper);
9373 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9374 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009375 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009376
9377 // First finger move.
9378 processId(mapper, FIRST_TRACKING_ID);
9379 processPosition(mapper, x1 + 1, y1 + 1);
9380 processPressure(mapper, RAW_PRESSURE_MAX);
9381 processSync(mapper);
9382 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9383 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009384 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009385
9386 // Second finger down.
9387 processSlot(mapper, SECOND_SLOT);
9388 processId(mapper, SECOND_TRACKING_ID);
9389 processPosition(mapper, x2, y2);
9390 processPressure(mapper, RAW_PRESSURE_MAX);
9391 processSync(mapper);
9392 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009393 ASSERT_EQ(ACTION_POINTER_1_DOWN, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009394 ASSERT_EQ(uint32_t(2), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009395
9396 // second finger up with some unexpected data.
9397 processSlot(mapper, SECOND_SLOT);
9398 processId(mapper, INVALID_TRACKING_ID);
9399 processPosition(mapper, x2, y2);
9400 processSync(mapper);
9401 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou5fd3e012021-12-30 15:20:32 -08009402 ASSERT_EQ(ACTION_POINTER_1_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009403 ASSERT_EQ(uint32_t(2), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009404
9405 // first finger up with some unexpected data.
9406 processSlot(mapper, FIRST_SLOT);
9407 processId(mapper, INVALID_TRACKING_ID);
9408 processPosition(mapper, x2, y2);
9409 processPressure(mapper, RAW_PRESSURE_MAX);
9410 processSync(mapper);
9411 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9412 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009413 ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
Arthur Hung9ad18942021-06-19 02:04:46 +00009414}
9415
Arpit Singh4b4a4572023-11-24 18:19:56 +00009416TEST_F(MultiTouchInputMapperTest, Reset_RepopulatesMultiTouchState) {
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009417 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009418 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009419 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009420 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009421
9422 // First finger down.
Arpit Singh4b4a4572023-11-24 18:19:56 +00009423 constexpr int32_t x1 = 100, y1 = 200, x2 = 300, y2 = 400;
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009424 processId(mapper, FIRST_TRACKING_ID);
Arpit Singh4b4a4572023-11-24 18:19:56 +00009425 processPosition(mapper, x1, y1);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009426 processPressure(mapper, RAW_PRESSURE_MAX);
9427 processSync(mapper);
9428 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9429 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
9430
9431 // Second finger down.
9432 processSlot(mapper, SECOND_SLOT);
9433 processId(mapper, SECOND_TRACKING_ID);
Arpit Singh4b4a4572023-11-24 18:19:56 +00009434 processPosition(mapper, x2, y2);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009435 processPressure(mapper, RAW_PRESSURE_MAX);
9436 processSync(mapper);
9437 ASSERT_NO_FATAL_FAILURE(
9438 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(ACTION_POINTER_1_DOWN)));
9439
Arpit Singh4b4a4572023-11-24 18:19:56 +00009440 // Set MT Slot state to be repopulated for the required slots
9441 std::vector<int32_t> mtSlotValues(RAW_SLOT_MAX + 1, -1);
9442 mtSlotValues[0] = FIRST_TRACKING_ID;
9443 mtSlotValues[1] = SECOND_TRACKING_ID;
9444 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_TRACKING_ID, mtSlotValues);
9445
9446 mtSlotValues[0] = x1;
9447 mtSlotValues[1] = x2;
9448 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_POSITION_X, mtSlotValues);
9449
9450 mtSlotValues[0] = y1;
9451 mtSlotValues[1] = y2;
9452 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_POSITION_Y, mtSlotValues);
9453
9454 mtSlotValues[0] = RAW_PRESSURE_MAX;
9455 mtSlotValues[1] = RAW_PRESSURE_MAX;
9456 mFakeEventHub->setMtSlotValues(EVENTHUB_ID, ABS_MT_PRESSURE, mtSlotValues);
9457
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009458 // Reset the mapper. When the mapper is reset, we expect the current multi-touch state to be
Arpit Singh4b4a4572023-11-24 18:19:56 +00009459 // repopulated. Resetting should cancel the ongoing gesture.
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00009460 resetMapper(mapper, ARBITRARY_TIME);
9461 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9462 WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009463
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009464 // Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
9465 // the existing touch state to generate a down event.
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009466 processPosition(mapper, 301, 302);
9467 processSync(mapper);
9468 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9469 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPressure(1.f))));
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009470 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9471 AllOf(WithMotionAction(ACTION_POINTER_1_DOWN), WithPressure(1.f))));
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009472
9473 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9474}
9475
Arpit Singh4bb0bd52023-12-20 14:41:10 +00009476TEST_F(MultiTouchInputMapperTest, Reset_PreservesLastTouchState_NoPointersDown) {
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009477 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009478 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009479 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009480 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009481
9482 // First finger touches down and releases.
9483 processId(mapper, FIRST_TRACKING_ID);
9484 processPosition(mapper, 100, 200);
9485 processPressure(mapper, RAW_PRESSURE_MAX);
9486 processSync(mapper);
9487 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9488 WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
9489 processId(mapper, INVALID_TRACKING_ID);
9490 processSync(mapper);
9491 ASSERT_NO_FATAL_FAILURE(
9492 mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
9493
9494 // Reset the mapper. When the mapper is reset, we expect it to restore the latest
9495 // raw state where no pointers are down.
Prabir Pradhanf5b4d7a2022-10-03 15:45:50 +00009496 resetMapper(mapper, ARBITRARY_TIME);
Prabir Pradhanafabcde2022-09-27 19:32:43 +00009497 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9498
9499 // Send an empty sync frame. Since there are no pointers, no events are generated.
9500 processSync(mapper);
9501 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
9502}
9503
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009504TEST_F(MultiTouchInputMapperTest, StylusSourceIsAddedDynamicallyFromToolType) {
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009505 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009506 prepareDisplay(ui::ROTATION_0);
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009507 prepareAxes(POSITION | ID | SLOT | PRESSURE | TOOL_TYPE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009508 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009509 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009510
9511 // Even if the device supports reporting the ABS_MT_TOOL_TYPE axis, which could give it the
9512 // ability to report MT_TOOL_PEN, we do not report the device as coming from a stylus source.
9513 // Due to limitations in the evdev protocol, we cannot say for certain that a device is capable
9514 // of reporting stylus events just because it supports ABS_MT_TOOL_TYPE.
9515 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
9516
9517 // However, if the device ever ends up reporting an event with MT_TOOL_PEN, it should be
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009518 // reported with the stylus source.
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009519 processId(mapper, FIRST_TRACKING_ID);
9520 processToolType(mapper, MT_TOOL_PEN);
9521 processPosition(mapper, 100, 200);
9522 processPressure(mapper, RAW_PRESSURE_MAX);
9523 processSync(mapper);
9524 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9525 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
9526 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009527 WithToolType(ToolType::STYLUS))));
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009528
Prabir Pradhan5d0d97d2022-11-17 01:06:01 +00009529 // Now that we know the device supports styluses, ensure that the device is re-configured with
9530 // the stylus source.
9531 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, mapper.getSources());
9532 {
9533 const auto& devices = mReader->getInputDevices();
9534 auto deviceInfo =
9535 std::find_if(devices.begin(), devices.end(),
9536 [](const InputDeviceInfo& info) { return info.getId() == DEVICE_ID; });
9537 LOG_ALWAYS_FATAL_IF(deviceInfo == devices.end(), "Cannot find InputDevice");
9538 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, deviceInfo->getSources());
9539 }
9540
9541 // Ensure the device was not reset to prevent interruptions of any ongoing gestures.
9542 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled());
9543
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009544 processId(mapper, INVALID_TRACKING_ID);
9545 processSync(mapper);
9546 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9547 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
9548 WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009549 WithToolType(ToolType::STYLUS))));
Prabir Pradhanf9a41282022-10-25 17:15:50 +00009550}
9551
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009552// --- MultiTouchInputMapperTest_ExternalDevice ---
9553
9554class MultiTouchInputMapperTest_ExternalDevice : public MultiTouchInputMapperTest {
9555protected:
Chris Yea52ade12020-08-27 16:49:20 -07009556 void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL); }
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009557};
9558
9559/**
9560 * Expect fallback to internal viewport if device is external and external viewport is not present.
9561 */
9562TEST_F(MultiTouchInputMapperTest_ExternalDevice, Viewports_Fallback) {
9563 prepareAxes(POSITION);
9564 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009565 prepareDisplay(ui::ROTATION_0);
Arpit Singha8c236b2023-04-25 13:56:05 +00009566 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009567
9568 ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
9569
9570 NotifyMotionArgs motionArgs;
9571
9572 // Expect the event to be sent to the internal viewport,
9573 // because an external viewport is not present.
9574 processPosition(mapper, 100, 100);
9575 processSync(mapper);
9576 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009577 ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, motionArgs.displayId);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009578
9579 // Expect the event to be sent to the external viewport if it is present.
Michael Wrightfe3de7d2020-07-02 19:05:30 +01009580 prepareSecondaryDisplay(ViewportType::EXTERNAL);
Nathaniel R. Lewisa7b82e12020-02-12 15:40:45 -08009581 processPosition(mapper, 100, 100);
9582 processSync(mapper);
9583 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9584 ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
9585}
Arthur Hung4197f6b2020-03-16 15:39:59 +08009586
Prabir Pradhan3ed7e352024-05-03 23:59:43 +00009587// TODO(b/281840344): Remove the test when the old touchpad stack is removed. It is currently
9588// unclear what the behavior of the touchpad logic in TouchInputMapper should do after the
9589// PointerChoreographer refactor.
9590TEST_F(MultiTouchInputMapperTest, DISABLED_Process_TouchpadPointer) {
Harry Cutts8722be92024-04-05 14:46:05 +00009591 // prepare device
Michael Wrighta9cf4192022-12-01 23:46:39 +00009592 prepareDisplay(ui::ROTATION_0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009593 prepareAxes(POSITION | ID | SLOT);
9594 mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
9595 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +00009596 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009597 // run uncaptured pointer tests - pushes out generic events
9598 // FINGER 0 DOWN
9599 processId(mapper, 3);
9600 processPosition(mapper, 100, 100);
9601 processKey(mapper, BTN_TOUCH, 1);
9602 processSync(mapper);
9603
9604 // start at (100,100), cursor should be at (0,0) * scale
9605 NotifyMotionArgs args;
9606 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9607 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
9608 ASSERT_NO_FATAL_FAILURE(
9609 assertPointerCoords(args.pointerCoords[0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
9610
9611 // FINGER 0 MOVE
9612 processPosition(mapper, 200, 200);
9613 processSync(mapper);
9614
9615 // compute scaling to help with touch position checking
9616 float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
9617 float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
9618 float scale =
9619 mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
9620
9621 // translate from (100,100) -> (200,200), cursor should have changed to (100,100) * scale)
9622 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9623 ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
9624 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], 100 * scale, 100 * scale, 0,
9625 0, 0, 0, 0, 0, 0, 0));
LiZhihong758eb562022-11-03 15:28:29 +08009626
9627 // BUTTON DOWN
9628 processKey(mapper, BTN_LEFT, 1);
9629 processSync(mapper);
9630
9631 // touchinputmapper design sends a move before button press
9632 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9633 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
9634 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9635 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_PRESS, args.action);
9636
9637 // BUTTON UP
9638 processKey(mapper, BTN_LEFT, 0);
9639 processSync(mapper);
9640
9641 // touchinputmapper design sends a move after button release
9642 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9643 ASSERT_EQ(AMOTION_EVENT_ACTION_BUTTON_RELEASE, args.action);
9644 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
9645 ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009646}
9647
Harry Cutts8722be92024-04-05 14:46:05 +00009648TEST_F(MultiTouchInputMapperTest, Touchpad_GetSources) {
Michael Wrighta9cf4192022-12-01 23:46:39 +00009649 prepareDisplay(ui::ROTATION_0);
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009650 prepareAxes(POSITION | ID | SLOT);
9651 mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
Hiroki Sato25040232024-02-22 17:21:22 +09009652 mFakePolicy->setPointerCapture(/*window=*/nullptr);
Arpit Singha8c236b2023-04-25 13:56:05 +00009653 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009654
Josep del Río2d8c79a2023-01-23 19:33:50 +00009655 // uncaptured touchpad should be a pointer device
9656 ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
Nathaniel R. Lewisd5665332018-02-22 13:31:42 -08009657}
9658
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009659// --- BluetoothMultiTouchInputMapperTest ---
9660
9661class BluetoothMultiTouchInputMapperTest : public MultiTouchInputMapperTest {
9662protected:
9663 void SetUp() override {
9664 InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL, BUS_BLUETOOTH);
9665 }
9666};
9667
9668TEST_F(BluetoothMultiTouchInputMapperTest, TimestampSmoothening) {
9669 addConfigurationProperty("touch.deviceType", "touchScreen");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009670 prepareDisplay(ui::ROTATION_0);
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009671 prepareAxes(POSITION | ID | SLOT | PRESSURE);
Arpit Singha8c236b2023-04-25 13:56:05 +00009672 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +00009673
9674 nsecs_t kernelEventTime = ARBITRARY_TIME;
9675 nsecs_t expectedEventTime = ARBITRARY_TIME;
9676 // Touch down.
9677 processId(mapper, FIRST_TRACKING_ID);
9678 processPosition(mapper, 100, 200);
9679 processPressure(mapper, RAW_PRESSURE_MAX);
9680 processSync(mapper, ARBITRARY_TIME);
9681 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9682 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithEventTime(ARBITRARY_TIME))));
9683
9684 // Process several events that come in quick succession, according to their timestamps.
9685 for (int i = 0; i < 3; i++) {
9686 constexpr static nsecs_t delta = ms2ns(1);
9687 static_assert(delta < MIN_BLUETOOTH_TIMESTAMP_DELTA);
9688 kernelEventTime += delta;
9689 expectedEventTime += MIN_BLUETOOTH_TIMESTAMP_DELTA;
9690
9691 processPosition(mapper, 101 + i, 201 + i);
9692 processSync(mapper, kernelEventTime);
9693 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9694 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
9695 WithEventTime(expectedEventTime))));
9696 }
9697
9698 // Release the touch.
9699 processId(mapper, INVALID_TRACKING_ID);
9700 processPressure(mapper, RAW_PRESSURE_MIN);
9701 processSync(mapper, ARBITRARY_TIME + ms2ns(50));
9702 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
9703 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
9704 WithEventTime(ARBITRARY_TIME + ms2ns(50)))));
9705}
9706
9707// --- MultiTouchPointerModeTest ---
9708
HQ Liue6983c72022-04-19 22:14:56 +00009709class MultiTouchPointerModeTest : public MultiTouchInputMapperTest {
9710protected:
9711 float mPointerMovementScale;
9712 float mPointerXZoomScale;
9713 void preparePointerMode(int xAxisResolution, int yAxisResolution) {
9714 addConfigurationProperty("touch.deviceType", "pointer");
Michael Wrighta9cf4192022-12-01 23:46:39 +00009715 prepareDisplay(ui::ROTATION_0);
HQ Liue6983c72022-04-19 22:14:56 +00009716
9717 prepareAxes(POSITION);
9718 prepareAbsoluteAxisResolution(xAxisResolution, yAxisResolution);
9719 // In order to enable swipe and freeform gesture in pointer mode, pointer capture
9720 // needs to be disabled, and the pointer gesture needs to be enabled.
Hiroki Sato25040232024-02-22 17:21:22 +09009721 mFakePolicy->setPointerCapture(/*window=*/nullptr);
HQ Liue6983c72022-04-19 22:14:56 +00009722 mFakePolicy->setPointerGestureEnabled(true);
HQ Liue6983c72022-04-19 22:14:56 +00009723
9724 float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
9725 float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
9726 mPointerMovementScale =
9727 mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
9728 mPointerXZoomScale =
9729 mFakePolicy->getPointerGestureZoomSpeedRatio() * displayDiagonal / rawDiagonal;
9730 }
9731
9732 void prepareAbsoluteAxisResolution(int xAxisResolution, int yAxisResolution) {
9733 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX,
9734 /*flat*/ 0,
9735 /*fuzz*/ 0, /*resolution*/ xAxisResolution);
9736 mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX,
9737 /*flat*/ 0,
9738 /*fuzz*/ 0, /*resolution*/ yAxisResolution);
9739 }
9740};
9741
9742/**
9743 * Two fingers down on a pointer mode touch pad. The width
9744 * of the two finger is larger than 1/4 of the touch pack diagnal length. However, it
9745 * is smaller than the fixed min physical length 30mm. Two fingers' distance must
9746 * be greater than the both value to be freeform gesture, so that after two
9747 * fingers start to move downwards, the gesture should be swipe.
9748 */
9749TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthSwipe) {
9750 // The min freeform gesture width is 25units/mm x 30mm = 750
9751 // which is greater than fraction of the diagnal length of the touchpad (349).
9752 // Thus, MaxSwipWidth is 750.
Harry Cutts33476232023-01-30 19:57:29 +00009753 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +00009754 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009755 NotifyMotionArgs motionArgs;
9756
9757 // Two fingers down at once.
9758 // The two fingers are 450 units apart, expects the current gesture to be PRESS
9759 // Pointer's initial position is used the [0,0] coordinate.
9760 int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125;
9761
9762 processId(mapper, FIRST_TRACKING_ID);
9763 processPosition(mapper, x1, y1);
9764 processMTSync(mapper);
9765 processId(mapper, SECOND_TRACKING_ID);
9766 processPosition(mapper, x2, y2);
9767 processMTSync(mapper);
9768 processSync(mapper);
9769
9770 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009771 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009772 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009773 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009774 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009775 ASSERT_NO_FATAL_FAILURE(
9776 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9777
9778 // It should be recognized as a SWIPE gesture when two fingers start to move down,
9779 // that there should be 1 pointer.
9780 int32_t movingDistance = 200;
9781 y1 += movingDistance;
9782 y2 += movingDistance;
9783
9784 processId(mapper, FIRST_TRACKING_ID);
9785 processPosition(mapper, x1, y1);
9786 processMTSync(mapper);
9787 processId(mapper, SECOND_TRACKING_ID);
9788 processPosition(mapper, x2, y2);
9789 processMTSync(mapper);
9790 processSync(mapper);
9791
9792 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009793 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009794 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009795 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009796 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009797 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
9798 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9799 0, 0, 0, 0));
9800}
9801
9802/**
9803 * Two fingers down on a pointer mode touch pad. The width of the two finger is larger
9804 * than the minimum freeform gesture width, 30mm. However, it is smaller than 1/4 of
9805 * the touch pack diagnal length. Two fingers' distance must be greater than the both
9806 * value to be freeform gesture, so that after two fingers start to move downwards,
9807 * the gesture should be swipe.
9808 */
9809TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthLowResolutionSwipe) {
9810 // The min freeform gesture width is 5units/mm x 30mm = 150
9811 // which is greater than fraction of the diagnal length of the touchpad (349).
9812 // Thus, MaxSwipWidth is the fraction of the diagnal length, 349.
Harry Cutts33476232023-01-30 19:57:29 +00009813 preparePointerMode(/*xResolution=*/5, /*yResolution=*/5);
Arpit Singha8c236b2023-04-25 13:56:05 +00009814 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009815 NotifyMotionArgs motionArgs;
9816
9817 // Two fingers down at once.
9818 // The two fingers are 250 units apart, expects the current gesture to be PRESS
9819 // Pointer's initial position is used the [0,0] coordinate.
9820 int32_t x1 = 100, y1 = 125, x2 = 350, y2 = 125;
9821
9822 processId(mapper, FIRST_TRACKING_ID);
9823 processPosition(mapper, x1, y1);
9824 processMTSync(mapper);
9825 processId(mapper, SECOND_TRACKING_ID);
9826 processPosition(mapper, x2, y2);
9827 processMTSync(mapper);
9828 processSync(mapper);
9829
9830 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009831 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009832 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009833 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009834 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009835 ASSERT_NO_FATAL_FAILURE(
9836 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9837
9838 // It should be recognized as a SWIPE gesture when two fingers start to move down,
9839 // and there should be 1 pointer.
9840 int32_t movingDistance = 200;
9841 y1 += movingDistance;
9842 y2 += movingDistance;
9843
9844 processId(mapper, FIRST_TRACKING_ID);
9845 processPosition(mapper, x1, y1);
9846 processMTSync(mapper);
9847 processId(mapper, SECOND_TRACKING_ID);
9848 processPosition(mapper, x2, y2);
9849 processMTSync(mapper);
9850 processSync(mapper);
9851
9852 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009853 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009854 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009855 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009856 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009857 // New coordinate is the scaled relative coordinate from the initial coordinate.
9858 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
9859 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9860 0, 0, 0, 0));
9861}
9862
9863/**
9864 * Touch the touch pad with two fingers with a distance wider than the minimum freeform
9865 * gesture width and 1/4 of the diagnal length of the touchpad. Expect to receive
9866 * freeform gestures after two fingers start to move downwards.
9867 */
9868TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthFreeform) {
Harry Cutts33476232023-01-30 19:57:29 +00009869 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +00009870 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
HQ Liue6983c72022-04-19 22:14:56 +00009871
9872 NotifyMotionArgs motionArgs;
9873
9874 // Two fingers down at once. Wider than the max swipe width.
9875 // The gesture is expected to be PRESS, then transformed to FREEFORM
9876 int32_t x1 = 100, y1 = 125, x2 = 900, y2 = 125;
9877
9878 processId(mapper, FIRST_TRACKING_ID);
9879 processPosition(mapper, x1, y1);
9880 processMTSync(mapper);
9881 processId(mapper, SECOND_TRACKING_ID);
9882 processPosition(mapper, x2, y2);
9883 processMTSync(mapper);
9884 processSync(mapper);
9885
9886 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009887 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009888 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009889 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009890 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009891 // One pointer for PRESS, and its coordinate is used as the origin for pointer coordinates.
9892 ASSERT_NO_FATAL_FAILURE(
9893 assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
9894
9895 int32_t movingDistance = 200;
9896
9897 // Move two fingers down, expect a cancel event because gesture is changing to freeform,
9898 // then two down events for two pointers.
9899 y1 += movingDistance;
9900 y2 += movingDistance;
9901
9902 processId(mapper, FIRST_TRACKING_ID);
9903 processPosition(mapper, x1, y1);
9904 processMTSync(mapper);
9905 processId(mapper, SECOND_TRACKING_ID);
9906 processPosition(mapper, x2, y2);
9907 processMTSync(mapper);
9908 processSync(mapper);
9909
9910 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
9911 // The previous PRESS gesture is cancelled, because it is transformed to freeform
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009912 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009913 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
9914 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009915 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009916 ASSERT_EQ(1U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009917 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
9918 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009919 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009920 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009921 ASSERT_EQ(2U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009922 ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN, motionArgs.action & AMOTION_EVENT_ACTION_MASK);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009923 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009924 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009925 // Two pointers' scaled relative coordinates from their initial centroid.
9926 // Initial y coordinates are 0 as y1 and y2 have the same value.
9927 float cookedX1 = (x1 - x2) / 2 * mPointerXZoomScale;
9928 float cookedX2 = (x2 - x1) / 2 * mPointerXZoomScale;
9929 // When pointers move, the new coordinates equal to the initial coordinates plus
9930 // scaled moving distance.
9931 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
9932 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9933 0, 0, 0, 0));
9934 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], cookedX2,
9935 movingDistance * mPointerMovementScale, 1, 0, 0, 0,
9936 0, 0, 0, 0));
9937
9938 // Move two fingers down again, expect one MOVE motion event.
9939 y1 += movingDistance;
9940 y2 += movingDistance;
9941
9942 processId(mapper, FIRST_TRACKING_ID);
9943 processPosition(mapper, x1, y1);
9944 processMTSync(mapper);
9945 processId(mapper, SECOND_TRACKING_ID);
9946 processPosition(mapper, x2, y2);
9947 processMTSync(mapper);
9948 processSync(mapper);
9949
9950 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009951 ASSERT_EQ(2U, motionArgs.getPointerCount());
HQ Liue6983c72022-04-19 22:14:56 +00009952 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009953 ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
Harry Cutts2800fb02022-09-15 13:49:23 +00009954 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
HQ Liue6983c72022-04-19 22:14:56 +00009955 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
9956 movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
9957 0, 0, 0, 0, 0));
9958 ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], cookedX2,
9959 movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
9960 0, 0, 0, 0, 0));
9961}
9962
Harry Cutts39b7ca22022-10-05 15:55:48 +00009963TEST_F(MultiTouchPointerModeTest, TwoFingerSwipeOffsets) {
Harry Cutts33476232023-01-30 19:57:29 +00009964 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Arpit Singha8c236b2023-04-25 13:56:05 +00009965 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Harry Cutts39b7ca22022-10-05 15:55:48 +00009966 NotifyMotionArgs motionArgs;
9967
9968 // Place two fingers down.
9969 int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125;
9970
9971 processId(mapper, FIRST_TRACKING_ID);
9972 processPosition(mapper, x1, y1);
9973 processMTSync(mapper);
9974 processId(mapper, SECOND_TRACKING_ID);
9975 processPosition(mapper, x2, y2);
9976 processMTSync(mapper);
9977 processSync(mapper);
9978
9979 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009980 ASSERT_EQ(1U, motionArgs.getPointerCount());
Harry Cutts39b7ca22022-10-05 15:55:48 +00009981 ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
9982 ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
9983 ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET));
9984 ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET));
9985
9986 // Move the two fingers down and to the left.
9987 int32_t movingDistance = 200;
9988 x1 -= movingDistance;
9989 y1 += movingDistance;
9990 x2 -= movingDistance;
9991 y2 += movingDistance;
9992
9993 processId(mapper, FIRST_TRACKING_ID);
9994 processPosition(mapper, x1, y1);
9995 processMTSync(mapper);
9996 processId(mapper, SECOND_TRACKING_ID);
9997 processPosition(mapper, x2, y2);
9998 processMTSync(mapper);
9999 processSync(mapper);
10000
10001 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -070010002 ASSERT_EQ(1U, motionArgs.getPointerCount());
Harry Cutts39b7ca22022-10-05 15:55:48 +000010003 ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
10004 ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
10005 ASSERT_LT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET), 0);
10006 ASSERT_GT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET), 0);
10007}
10008
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010009TEST_F(MultiTouchPointerModeTest, WhenViewportActiveStatusChanged_PointerGestureIsReset) {
Harry Cutts33476232023-01-30 19:57:29 +000010010 preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010011 mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
Arpit Singha8c236b2023-04-25 13:56:05 +000010012 MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010013 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
10014
10015 // Start a stylus gesture.
10016 processKey(mapper, BTN_TOOL_PEN, 1);
10017 processId(mapper, FIRST_TRACKING_ID);
10018 processPosition(mapper, 100, 200);
10019 processSync(mapper);
10020 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10021 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
10022 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010023 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010024 // TODO(b/257078296): Pointer mode generates extra event.
10025 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10026 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
10027 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010028 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010029 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
10030
10031 // Make the viewport inactive. This will put the device in disabled mode, and the ongoing stylus
10032 // gesture should be disabled.
10033 auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
10034 viewport->isActive = false;
10035 mFakePolicy->updateViewport(*viewport);
Prabir Pradhan4bf6d452023-04-18 21:26:56 +000010036 configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010037 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10038 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
10039 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010040 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010041 // TODO(b/257078296): Pointer mode generates extra event.
10042 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
10043 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
10044 WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010045 WithToolType(ToolType::STYLUS))));
Prabir Pradhanb80b6c02022-11-02 20:05:13 +000010046 ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
10047}
10048
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010049// --- PeripheralControllerTest ---
Chris Yee2b1e5c2021-03-10 22:45:12 -080010050
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010051class PeripheralControllerTest : public testing::Test {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010052protected:
10053 static const char* DEVICE_NAME;
10054 static const char* DEVICE_LOCATION;
10055 static const int32_t DEVICE_ID;
10056 static const int32_t DEVICE_GENERATION;
10057 static const int32_t DEVICE_CONTROLLER_NUMBER;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010058 static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010059 static const int32_t EVENTHUB_ID;
10060
10061 std::shared_ptr<FakeEventHub> mFakeEventHub;
10062 sp<FakeInputReaderPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010063 std::unique_ptr<TestInputListener> mFakeListener;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010064 std::unique_ptr<InstrumentedInputReader> mReader;
10065 std::shared_ptr<InputDevice> mDevice;
10066
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010067 virtual void SetUp(ftl::Flags<InputDeviceClass> classes) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010068 mFakeEventHub = std::make_unique<FakeEventHub>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010069 mFakePolicy = sp<FakeInputReaderPolicy>::make();
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010070 mFakeListener = std::make_unique<TestInputListener>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010071 mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010072 *mFakeListener);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010073 mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes);
10074 }
10075
10076 void SetUp() override { SetUp(DEVICE_CLASSES); }
10077
10078 void TearDown() override {
Siarhei Vishniakou18050092021-09-01 13:32:49 -070010079 mFakeListener.reset();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010080 mFakePolicy.clear();
10081 }
10082
Chris Yee2b1e5c2021-03-10 22:45:12 -080010083 std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
10084 const std::string& location, int32_t eventHubId,
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010085 ftl::Flags<InputDeviceClass> classes) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010086 InputDeviceIdentifier identifier;
10087 identifier.name = name;
10088 identifier.location = location;
10089 std::shared_ptr<InputDevice> device =
10090 std::make_shared<InputDevice>(mReader->getContext(), deviceId, DEVICE_GENERATION,
10091 identifier);
10092 mReader->pushNextDevice(device);
10093 mFakeEventHub->addDevice(eventHubId, name, classes);
10094 mReader->loopOnce();
10095 return device;
10096 }
10097
10098 template <class T, typename... Args>
10099 T& addControllerAndConfigure(Args... args) {
10100 T& controller = mDevice->addController<T>(EVENTHUB_ID, args...);
10101
10102 return controller;
10103 }
10104};
10105
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010106const char* PeripheralControllerTest::DEVICE_NAME = "device";
10107const char* PeripheralControllerTest::DEVICE_LOCATION = "BLUETOOTH";
10108const int32_t PeripheralControllerTest::DEVICE_ID = END_RESERVED_ID + 1000;
10109const int32_t PeripheralControllerTest::DEVICE_GENERATION = 2;
10110const int32_t PeripheralControllerTest::DEVICE_CONTROLLER_NUMBER = 0;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070010111const ftl::Flags<InputDeviceClass> PeripheralControllerTest::DEVICE_CLASSES =
10112 ftl::Flags<InputDeviceClass>(0); // not needed for current tests
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010113const int32_t PeripheralControllerTest::EVENTHUB_ID = 1;
Chris Yee2b1e5c2021-03-10 22:45:12 -080010114
10115// --- BatteryControllerTest ---
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010116class BatteryControllerTest : public PeripheralControllerTest {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010117protected:
10118 void SetUp() override {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010119 PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::BATTERY);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010120 }
10121};
10122
10123TEST_F(BatteryControllerTest, GetBatteryCapacity) {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010124 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010125
Harry Cuttsa5b71292022-11-28 12:56:17 +000010126 ASSERT_TRUE(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY));
10127 ASSERT_EQ(controller.getBatteryCapacity(FakeEventHub::DEFAULT_BATTERY).value_or(-1),
10128 FakeEventHub::BATTERY_CAPACITY);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010129}
10130
10131TEST_F(BatteryControllerTest, GetBatteryStatus) {
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010132 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010133
Harry Cuttsa5b71292022-11-28 12:56:17 +000010134 ASSERT_TRUE(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY));
10135 ASSERT_EQ(controller.getBatteryStatus(FakeEventHub::DEFAULT_BATTERY).value_or(-1),
10136 FakeEventHub::BATTERY_STATUS);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010137}
10138
10139// --- LightControllerTest ---
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010140class LightControllerTest : public PeripheralControllerTest {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010141protected:
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010142 void SetUp() override {
10143 PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::LIGHT);
10144 }
Chris Yee2b1e5c2021-03-10 22:45:12 -080010145};
10146
Chris Ye85758332021-05-16 23:05:17 -070010147TEST_F(LightControllerTest, MonoLight) {
10148 RawLightInfo infoMono = {.id = 1,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010149 .name = "mono_light",
Chris Ye85758332021-05-16 23:05:17 -070010150 .maxBrightness = 255,
10151 .flags = InputLightClass::BRIGHTNESS,
10152 .path = ""};
10153 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010154
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010155 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010156 InputDeviceInfo info;
10157 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010158 std::vector<InputDeviceLightInfo> lights = info.getLights();
10159 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010160 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10161 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10162
10163 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_BRIGHTNESS));
10164 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_BRIGHTNESS);
10165}
10166
DingYong99f2c3c2023-12-20 15:46:06 +080010167TEST_F(LightControllerTest, MonoKeyboardMuteLight) {
10168 RawLightInfo infoMono = {.id = 1,
10169 .name = "mono_keyboard_mute",
10170 .maxBrightness = 255,
10171 .flags = InputLightClass::BRIGHTNESS |
10172 InputLightClass::KEYBOARD_MIC_MUTE,
10173 .path = ""};
10174 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10175
10176 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10177 std::list<NotifyArgs> unused =
10178 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10179 /*changes=*/{});
10180
10181 InputDeviceInfo info;
10182 controller.populateDeviceInfo(&info);
10183 std::vector<InputDeviceLightInfo> lights = info.getLights();
10184 ASSERT_EQ(1U, lights.size());
10185 ASSERT_EQ(InputDeviceLightType::KEYBOARD_MIC_MUTE, lights[0].type);
10186 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10187}
10188
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010189TEST_F(LightControllerTest, MonoKeyboardBacklight) {
10190 RawLightInfo infoMono = {.id = 1,
10191 .name = "mono_keyboard_backlight",
10192 .maxBrightness = 255,
10193 .flags = InputLightClass::BRIGHTNESS |
10194 InputLightClass::KEYBOARD_BACKLIGHT,
10195 .path = ""};
10196 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10197
10198 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10199 InputDeviceInfo info;
10200 controller.populateDeviceInfo(&info);
10201 std::vector<InputDeviceLightInfo> lights = info.getLights();
10202 ASSERT_EQ(1U, lights.size());
10203 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10204 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010205
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010206 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_BRIGHTNESS));
10207 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_BRIGHTNESS);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010208}
10209
Vaibhav Devmurari16c24192023-05-04 15:20:12 +000010210TEST_F(LightControllerTest, Ignore_MonoLight_WithPreferredBacklightLevels) {
10211 RawLightInfo infoMono = {.id = 1,
10212 .name = "mono_light",
10213 .maxBrightness = 255,
10214 .flags = InputLightClass::BRIGHTNESS,
10215 .path = ""};
10216 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10217 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10218 "0,100,200");
10219
10220 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10221 std::list<NotifyArgs> unused =
10222 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10223 /*changes=*/{});
10224
10225 InputDeviceInfo info;
10226 controller.populateDeviceInfo(&info);
10227 std::vector<InputDeviceLightInfo> lights = info.getLights();
10228 ASSERT_EQ(1U, lights.size());
10229 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10230}
10231
10232TEST_F(LightControllerTest, KeyboardBacklight_WithNoPreferredBacklightLevels) {
10233 RawLightInfo infoMono = {.id = 1,
10234 .name = "mono_keyboard_backlight",
10235 .maxBrightness = 255,
10236 .flags = InputLightClass::BRIGHTNESS |
10237 InputLightClass::KEYBOARD_BACKLIGHT,
10238 .path = ""};
10239 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10240
10241 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10242 std::list<NotifyArgs> unused =
10243 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10244 /*changes=*/{});
10245
10246 InputDeviceInfo info;
10247 controller.populateDeviceInfo(&info);
10248 std::vector<InputDeviceLightInfo> lights = info.getLights();
10249 ASSERT_EQ(1U, lights.size());
10250 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10251}
10252
10253TEST_F(LightControllerTest, KeyboardBacklight_WithPreferredBacklightLevels) {
10254 RawLightInfo infoMono = {.id = 1,
10255 .name = "mono_keyboard_backlight",
10256 .maxBrightness = 255,
10257 .flags = InputLightClass::BRIGHTNESS |
10258 InputLightClass::KEYBOARD_BACKLIGHT,
10259 .path = ""};
10260 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10261 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10262 "0,100,200");
10263
10264 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10265 std::list<NotifyArgs> unused =
10266 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10267 /*changes=*/{});
10268
10269 InputDeviceInfo info;
10270 controller.populateDeviceInfo(&info);
10271 std::vector<InputDeviceLightInfo> lights = info.getLights();
10272 ASSERT_EQ(1U, lights.size());
10273 ASSERT_EQ(3U, lights[0].preferredBrightnessLevels.size());
10274 std::set<BrightnessLevel>::iterator it = lights[0].preferredBrightnessLevels.begin();
10275 ASSERT_EQ(BrightnessLevel(0), *it);
10276 std::advance(it, 1);
10277 ASSERT_EQ(BrightnessLevel(100), *it);
10278 std::advance(it, 1);
10279 ASSERT_EQ(BrightnessLevel(200), *it);
10280}
10281
10282TEST_F(LightControllerTest, KeyboardBacklight_WithWrongPreferredBacklightLevels) {
10283 RawLightInfo infoMono = {.id = 1,
10284 .name = "mono_keyboard_backlight",
10285 .maxBrightness = 255,
10286 .flags = InputLightClass::BRIGHTNESS |
10287 InputLightClass::KEYBOARD_BACKLIGHT,
10288 .path = ""};
10289 mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
10290 mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "keyboard.backlight.brightnessLevels",
10291 "0,100,200,300,400,500");
10292
10293 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10294 std::list<NotifyArgs> unused =
10295 mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
10296 /*changes=*/{});
10297
10298 InputDeviceInfo info;
10299 controller.populateDeviceInfo(&info);
10300 std::vector<InputDeviceLightInfo> lights = info.getLights();
10301 ASSERT_EQ(1U, lights.size());
10302 ASSERT_EQ(0U, lights[0].preferredBrightnessLevels.size());
10303}
10304
Chris Yee2b1e5c2021-03-10 22:45:12 -080010305TEST_F(LightControllerTest, RGBLight) {
10306 RawLightInfo infoRed = {.id = 1,
10307 .name = "red",
10308 .maxBrightness = 255,
10309 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED,
10310 .path = ""};
10311 RawLightInfo infoGreen = {.id = 2,
10312 .name = "green",
10313 .maxBrightness = 255,
10314 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN,
10315 .path = ""};
10316 RawLightInfo infoBlue = {.id = 3,
10317 .name = "blue",
10318 .maxBrightness = 255,
10319 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE,
10320 .path = ""};
10321 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10322 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10323 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10324
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010325 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010326 InputDeviceInfo info;
10327 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010328 std::vector<InputDeviceLightInfo> lights = info.getLights();
10329 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010330 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10331 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10332 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10333
10334 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10335 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10336}
10337
10338TEST_F(LightControllerTest, CorrectRGBKeyboardBacklight) {
10339 RawLightInfo infoRed = {.id = 1,
10340 .name = "red_keyboard_backlight",
10341 .maxBrightness = 255,
10342 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED |
10343 InputLightClass::KEYBOARD_BACKLIGHT,
10344 .path = ""};
10345 RawLightInfo infoGreen = {.id = 2,
10346 .name = "green_keyboard_backlight",
10347 .maxBrightness = 255,
10348 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN |
10349 InputLightClass::KEYBOARD_BACKLIGHT,
10350 .path = ""};
10351 RawLightInfo infoBlue = {.id = 3,
10352 .name = "blue_keyboard_backlight",
10353 .maxBrightness = 255,
10354 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE |
10355 InputLightClass::KEYBOARD_BACKLIGHT,
10356 .path = ""};
10357 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10358 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10359 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10360
10361 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10362 InputDeviceInfo info;
10363 controller.populateDeviceInfo(&info);
10364 std::vector<InputDeviceLightInfo> lights = info.getLights();
10365 ASSERT_EQ(1U, lights.size());
10366 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10367 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10368 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10369
10370 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10371 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10372}
10373
10374TEST_F(LightControllerTest, IncorrectRGBKeyboardBacklight) {
10375 RawLightInfo infoRed = {.id = 1,
10376 .name = "red",
10377 .maxBrightness = 255,
10378 .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED,
10379 .path = ""};
10380 RawLightInfo infoGreen = {.id = 2,
10381 .name = "green",
10382 .maxBrightness = 255,
10383 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN,
10384 .path = ""};
10385 RawLightInfo infoBlue = {.id = 3,
10386 .name = "blue",
10387 .maxBrightness = 255,
10388 .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE,
10389 .path = ""};
10390 RawLightInfo infoGlobal = {.id = 3,
10391 .name = "global_keyboard_backlight",
10392 .maxBrightness = 255,
10393 .flags = InputLightClass::BRIGHTNESS | InputLightClass::GLOBAL |
10394 InputLightClass::KEYBOARD_BACKLIGHT,
10395 .path = ""};
10396 mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
10397 mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
10398 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
10399 mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoGlobal));
10400
10401 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10402 InputDeviceInfo info;
10403 controller.populateDeviceInfo(&info);
10404 std::vector<InputDeviceLightInfo> lights = info.getLights();
10405 ASSERT_EQ(1U, lights.size());
10406 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10407 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10408 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010409
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010410 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10411 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010412}
10413
10414TEST_F(LightControllerTest, MultiColorRGBLight) {
10415 RawLightInfo infoColor = {.id = 1,
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010416 .name = "multi_color",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010417 .maxBrightness = 255,
10418 .flags = InputLightClass::BRIGHTNESS |
10419 InputLightClass::MULTI_INTENSITY |
10420 InputLightClass::MULTI_INDEX,
10421 .path = ""};
10422
10423 mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
10424
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010425 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010426 InputDeviceInfo info;
10427 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010428 std::vector<InputDeviceLightInfo> lights = info.getLights();
10429 ASSERT_EQ(1U, lights.size());
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010430 ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
10431 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10432 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10433
10434 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10435 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
10436}
10437
10438TEST_F(LightControllerTest, MultiColorRGBKeyboardBacklight) {
10439 RawLightInfo infoColor = {.id = 1,
10440 .name = "multi_color_keyboard_backlight",
10441 .maxBrightness = 255,
10442 .flags = InputLightClass::BRIGHTNESS |
10443 InputLightClass::MULTI_INTENSITY |
10444 InputLightClass::MULTI_INDEX |
10445 InputLightClass::KEYBOARD_BACKLIGHT,
10446 .path = ""};
10447
10448 mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
10449
10450 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10451 InputDeviceInfo info;
10452 controller.populateDeviceInfo(&info);
10453 std::vector<InputDeviceLightInfo> lights = info.getLights();
10454 ASSERT_EQ(1U, lights.size());
10455 ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
10456 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10457 ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010458
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010459 ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10460 ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010461}
10462
Josep del Rioa1046a82023-08-24 19:57:27 +000010463TEST_F(LightControllerTest, SonyPlayerIdLight) {
Chris Yee2b1e5c2021-03-10 22:45:12 -080010464 RawLightInfo info1 = {.id = 1,
Josep del Rioa1046a82023-08-24 19:57:27 +000010465 .name = "sony1",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010466 .maxBrightness = 255,
10467 .flags = InputLightClass::BRIGHTNESS,
10468 .path = ""};
10469 RawLightInfo info2 = {.id = 2,
Josep del Rioa1046a82023-08-24 19:57:27 +000010470 .name = "sony2",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010471 .maxBrightness = 255,
10472 .flags = InputLightClass::BRIGHTNESS,
10473 .path = ""};
10474 RawLightInfo info3 = {.id = 3,
Josep del Rioa1046a82023-08-24 19:57:27 +000010475 .name = "sony3",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010476 .maxBrightness = 255,
10477 .flags = InputLightClass::BRIGHTNESS,
10478 .path = ""};
10479 RawLightInfo info4 = {.id = 4,
Josep del Rioa1046a82023-08-24 19:57:27 +000010480 .name = "sony4",
Chris Yee2b1e5c2021-03-10 22:45:12 -080010481 .maxBrightness = 255,
10482 .flags = InputLightClass::BRIGHTNESS,
10483 .path = ""};
10484 mFakeEventHub->addRawLightInfo(info1.id, std::move(info1));
10485 mFakeEventHub->addRawLightInfo(info2.id, std::move(info2));
10486 mFakeEventHub->addRawLightInfo(info3.id, std::move(info3));
10487 mFakeEventHub->addRawLightInfo(info4.id, std::move(info4));
10488
Chris Ye1dd2e5c2021-04-04 23:12:41 -070010489 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
Chris Yee2b1e5c2021-03-10 22:45:12 -080010490 InputDeviceInfo info;
10491 controller.populateDeviceInfo(&info);
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010492 std::vector<InputDeviceLightInfo> lights = info.getLights();
10493 ASSERT_EQ(1U, lights.size());
Josep del Rioa1046a82023-08-24 19:57:27 +000010494 ASSERT_STREQ("sony", lights[0].name.c_str());
10495 ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
10496 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10497 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
10498
10499 ASSERT_FALSE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10500 ASSERT_TRUE(controller.setLightPlayerId(lights[0].id, LIGHT_PLAYER_ID));
10501 ASSERT_EQ(controller.getLightPlayerId(lights[0].id).value_or(-1), LIGHT_PLAYER_ID);
10502 ASSERT_STREQ("sony", lights[0].name.c_str());
10503}
10504
10505TEST_F(LightControllerTest, PlayerIdLight) {
10506 RawLightInfo info1 = {.id = 1,
10507 .name = "player-1",
10508 .maxBrightness = 255,
10509 .flags = InputLightClass::BRIGHTNESS,
10510 .path = ""};
10511 RawLightInfo info2 = {.id = 2,
10512 .name = "player-2",
10513 .maxBrightness = 255,
10514 .flags = InputLightClass::BRIGHTNESS,
10515 .path = ""};
10516 RawLightInfo info3 = {.id = 3,
10517 .name = "player-3",
10518 .maxBrightness = 255,
10519 .flags = InputLightClass::BRIGHTNESS,
10520 .path = ""};
10521 RawLightInfo info4 = {.id = 4,
10522 .name = "player-4",
10523 .maxBrightness = 255,
10524 .flags = InputLightClass::BRIGHTNESS,
10525 .path = ""};
10526 mFakeEventHub->addRawLightInfo(info1.id, std::move(info1));
10527 mFakeEventHub->addRawLightInfo(info2.id, std::move(info2));
10528 mFakeEventHub->addRawLightInfo(info3.id, std::move(info3));
10529 mFakeEventHub->addRawLightInfo(info4.id, std::move(info4));
10530
10531 PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
10532 InputDeviceInfo info;
10533 controller.populateDeviceInfo(&info);
10534 std::vector<InputDeviceLightInfo> lights = info.getLights();
10535 ASSERT_EQ(1U, lights.size());
10536 ASSERT_STREQ("player", lights[0].name.c_str());
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010537 ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
Vaibhav Devmurari82b37d62022-09-12 13:36:48 +000010538 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
10539 ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
Chris Yee2b1e5c2021-03-10 22:45:12 -080010540
Siarhei Vishniakou1983a712021-06-04 19:27:09 +000010541 ASSERT_FALSE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
10542 ASSERT_TRUE(controller.setLightPlayerId(lights[0].id, LIGHT_PLAYER_ID));
10543 ASSERT_EQ(controller.getLightPlayerId(lights[0].id).value_or(-1), LIGHT_PLAYER_ID);
Chris Yee2b1e5c2021-03-10 22:45:12 -080010544}
10545
Michael Wrightd02c5b62014-02-10 15:10:22 -080010546} // namespace android