blob: fbafbadb4427a8d0a206c0b9d4f83108447985c6 [file] [log] [blame]
Siarhei Vishniakou979f2d82023-05-16 14:26:24 -07001/*
2 * Copyright 2023 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
17#include "TouchpadInputMapper.h"
18
19#include <android-base/logging.h>
20#include <gtest/gtest.h>
21
Byoungho Jungee6268f2023-10-30 17:27:26 +090022#include <com_android_input_flags.h>
Siarhei Vishniakou979f2d82023-05-16 14:26:24 -070023#include <thread>
24#include "FakePointerController.h"
25#include "InputMapperTest.h"
26#include "InterfaceMocks.h"
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000027#include "TestEventMatchers.h"
Siarhei Vishniakou979f2d82023-05-16 14:26:24 -070028
29#define TAG "TouchpadInputMapper_test"
30
31namespace android {
32
33using testing::Return;
34using testing::VariantWith;
35constexpr auto ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
36constexpr auto ACTION_UP = AMOTION_EVENT_ACTION_UP;
37constexpr auto BUTTON_PRESS = AMOTION_EVENT_ACTION_BUTTON_PRESS;
38constexpr auto BUTTON_RELEASE = AMOTION_EVENT_ACTION_BUTTON_RELEASE;
39constexpr auto HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Harry Cutts379ea422023-12-21 15:31:47 +000040constexpr auto HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
41constexpr auto HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Byoungho Jungee6268f2023-10-30 17:27:26 +090042constexpr int32_t DISPLAY_ID = 0;
43constexpr int32_t DISPLAY_WIDTH = 480;
44constexpr int32_t DISPLAY_HEIGHT = 800;
45constexpr std::optional<uint8_t> NO_PORT = std::nullopt; // no physical port is specified
46
47namespace input_flags = com::android::input::flags;
Siarhei Vishniakou979f2d82023-05-16 14:26:24 -070048
49/**
50 * Unit tests for TouchpadInputMapper.
51 */
Byoungho Jungee6268f2023-10-30 17:27:26 +090052class TouchpadInputMapperTestBase : public InputMapperUnitTest {
Siarhei Vishniakou979f2d82023-05-16 14:26:24 -070053protected:
54 void SetUp() override {
55 InputMapperUnitTest::SetUp();
56
57 // Present scan codes: BTN_TOUCH and BTN_TOOL_FINGER
58 expectScanCodes(/*present=*/true,
59 {BTN_LEFT, BTN_RIGHT, BTN_TOOL_FINGER, BTN_TOOL_QUINTTAP, BTN_TOUCH,
60 BTN_TOOL_DOUBLETAP, BTN_TOOL_TRIPLETAP, BTN_TOOL_QUADTAP});
61 // Missing scan codes that the mapper checks for.
62 expectScanCodes(/*present=*/false,
63 {BTN_TOOL_PEN, BTN_TOOL_RUBBER, BTN_TOOL_BRUSH, BTN_TOOL_PENCIL,
64 BTN_TOOL_AIRBRUSH});
65
66 // Current scan code state - all keys are UP by default
67 setScanCodeState(KeyState::UP, {BTN_TOUCH, BTN_STYLUS,
68 BTN_STYLUS2, BTN_0,
69 BTN_TOOL_FINGER, BTN_TOOL_PEN,
70 BTN_TOOL_RUBBER, BTN_TOOL_BRUSH,
71 BTN_TOOL_PENCIL, BTN_TOOL_AIRBRUSH,
72 BTN_TOOL_MOUSE, BTN_TOOL_LENS,
73 BTN_TOOL_DOUBLETAP, BTN_TOOL_TRIPLETAP,
74 BTN_TOOL_QUADTAP, BTN_TOOL_QUINTTAP,
75 BTN_LEFT, BTN_RIGHT,
76 BTN_MIDDLE, BTN_BACK,
77 BTN_SIDE, BTN_FORWARD,
78 BTN_EXTRA, BTN_TASK});
79
80 setKeyCodeState(KeyState::UP,
81 {AKEYCODE_STYLUS_BUTTON_PRIMARY, AKEYCODE_STYLUS_BUTTON_SECONDARY});
82
83 // Key mappings
84 EXPECT_CALL(mMockEventHub,
85 mapKey(EVENTHUB_ID, BTN_LEFT, /*usageCode=*/0, /*metaState=*/0, testing::_,
86 testing::_, testing::_))
87 .WillRepeatedly(Return(NAME_NOT_FOUND));
88
89 // Input properties - only INPUT_PROP_BUTTONPAD
90 EXPECT_CALL(mMockEventHub, hasInputProperty(EVENTHUB_ID, INPUT_PROP_BUTTONPAD))
91 .WillRepeatedly(Return(true));
92 EXPECT_CALL(mMockEventHub, hasInputProperty(EVENTHUB_ID, INPUT_PROP_SEMI_MT))
93 .WillRepeatedly(Return(false));
94
95 // Axes that the device has
96 setupAxis(ABS_MT_SLOT, /*valid=*/true, /*min=*/0, /*max=*/4, /*resolution=*/0);
97 setupAxis(ABS_MT_POSITION_X, /*valid=*/true, /*min=*/0, /*max=*/2000, /*resolution=*/24);
98 setupAxis(ABS_MT_POSITION_Y, /*valid=*/true, /*min=*/0, /*max=*/1000, /*resolution=*/24);
99 setupAxis(ABS_MT_PRESSURE, /*valid=*/true, /*min*/ 0, /*max=*/255, /*resolution=*/0);
100 // Axes that the device does not have
101 setupAxis(ABS_MT_ORIENTATION, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0);
102 setupAxis(ABS_MT_TOUCH_MAJOR, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0);
103 setupAxis(ABS_MT_TOUCH_MINOR, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0);
104 setupAxis(ABS_MT_WIDTH_MAJOR, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0);
105 setupAxis(ABS_MT_WIDTH_MINOR, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0);
Arpit Singh4b4a4572023-11-24 18:19:56 +0000106 setupAxis(ABS_MT_TRACKING_ID, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0);
107 setupAxis(ABS_MT_DISTANCE, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0);
108 setupAxis(ABS_MT_TOOL_TYPE, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0);
Siarhei Vishniakou979f2d82023-05-16 14:26:24 -0700109
110 EXPECT_CALL(mMockEventHub, getAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT, testing::_))
111 .WillRepeatedly([](int32_t eventHubId, int32_t, int32_t* outValue) {
112 *outValue = 0;
113 return OK;
114 });
Arpit Singh4b4a4572023-11-24 18:19:56 +0000115 EXPECT_CALL(mMockEventHub, getMtSlotValues(EVENTHUB_ID, testing::_, testing::_))
116 .WillRepeatedly([]() -> base::Result<std::vector<int32_t>> {
117 return base::ResultError("Axis not supported", NAME_NOT_FOUND);
118 });
Harry Cutts1b5bde42023-12-18 16:08:29 +0000119 createDevice();
Siarhei Vishniakou979f2d82023-05-16 14:26:24 -0700120 mMapper = createInputMapper<TouchpadInputMapper>(*mDeviceContext, mReaderConfiguration);
121 }
122};
123
Byoungho Jungee6268f2023-10-30 17:27:26 +0900124class TouchpadInputMapperTest : public TouchpadInputMapperTestBase {
125protected:
126 void SetUp() override {
127 input_flags::enable_pointer_choreographer(false);
128 TouchpadInputMapperTestBase::SetUp();
129 }
130};
131
Siarhei Vishniakou979f2d82023-05-16 14:26:24 -0700132/**
133 * Start moving the finger and then click the left touchpad button. Check whether HOVER_EXIT is
134 * generated when hovering stops. Currently, it is not.
135 * In the current implementation, HOVER_MOVE and ACTION_DOWN events are not sent out right away,
136 * but only after the button is released.
137 */
138TEST_F(TouchpadInputMapperTest, HoverAndLeftButtonPress) {
139 std::list<NotifyArgs> args;
140
141 args += process(EV_ABS, ABS_MT_TRACKING_ID, 1);
142 args += process(EV_KEY, BTN_TOUCH, 1);
143 setScanCodeState(KeyState::DOWN, {BTN_TOOL_FINGER});
144 args += process(EV_KEY, BTN_TOOL_FINGER, 1);
145 args += process(EV_ABS, ABS_MT_POSITION_X, 50);
146 args += process(EV_ABS, ABS_MT_POSITION_Y, 50);
147 args += process(EV_ABS, ABS_MT_PRESSURE, 1);
148 args += process(EV_SYN, SYN_REPORT, 0);
149 ASSERT_THAT(args, testing::IsEmpty());
150
151 // Without this sleep, the test fails.
152 // TODO(b/284133337): Figure out whether this can be removed
153 std::this_thread::sleep_for(std::chrono::milliseconds(20));
154
155 args += process(EV_KEY, BTN_LEFT, 1);
156 setScanCodeState(KeyState::DOWN, {BTN_LEFT});
157 args += process(EV_SYN, SYN_REPORT, 0);
158
159 args += process(EV_KEY, BTN_LEFT, 0);
160 setScanCodeState(KeyState::UP, {BTN_LEFT});
161 args += process(EV_SYN, SYN_REPORT, 0);
162 ASSERT_THAT(args,
Harry Cutts379ea422023-12-21 15:31:47 +0000163 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_ENTER)),
164 VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE)),
165 VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_EXIT)),
Siarhei Vishniakou979f2d82023-05-16 14:26:24 -0700166 VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_DOWN)),
167 VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_PRESS)),
168 VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
Harry Cutts48e7a402023-07-07 15:22:40 +0000169 VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP)),
Harry Cutts379ea422023-12-21 15:31:47 +0000170 VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_ENTER))));
Siarhei Vishniakou979f2d82023-05-16 14:26:24 -0700171
172 // Liftoff
173 args.clear();
174 args += process(EV_ABS, ABS_MT_PRESSURE, 0);
175 args += process(EV_ABS, ABS_MT_TRACKING_ID, -1);
176 args += process(EV_KEY, BTN_TOUCH, 0);
177 setScanCodeState(KeyState::UP, {BTN_TOOL_FINGER});
178 args += process(EV_KEY, BTN_TOOL_FINGER, 0);
179 args += process(EV_SYN, SYN_REPORT, 0);
180 ASSERT_THAT(args, testing::IsEmpty());
181}
182
Byoungho Jungee6268f2023-10-30 17:27:26 +0900183class TouchpadInputMapperTestWithChoreographer : public TouchpadInputMapperTestBase {
184protected:
185 void SetUp() override {
186 input_flags::enable_pointer_choreographer(true);
187 TouchpadInputMapperTestBase::SetUp();
188 }
189};
190
Prabir Pradhancc7268a2023-11-16 18:54:13 +0000191// TODO(b/311416205): De-duplicate the test cases after the refactoring is complete and the flagging
192// logic can be removed.
Byoungho Jungee6268f2023-10-30 17:27:26 +0900193/**
194 * Start moving the finger and then click the left touchpad button. Check whether HOVER_EXIT is
195 * generated when hovering stops. Currently, it is not.
196 * In the current implementation, HOVER_MOVE and ACTION_DOWN events are not sent out right away,
197 * but only after the button is released.
198 */
199TEST_F(TouchpadInputMapperTestWithChoreographer, HoverAndLeftButtonPress) {
200 mFakePolicy->setDefaultPointerDisplayId(DISPLAY_ID);
201 mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
202 /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL);
203
204 std::list<NotifyArgs> args;
205
206 args += mMapper->reconfigure(systemTime(SYSTEM_TIME_MONOTONIC), mReaderConfiguration,
207 InputReaderConfiguration::Change::DISPLAY_INFO);
208 ASSERT_THAT(args, testing::IsEmpty());
209
210 args += process(EV_ABS, ABS_MT_TRACKING_ID, 1);
211 args += process(EV_KEY, BTN_TOUCH, 1);
212 setScanCodeState(KeyState::DOWN, {BTN_TOOL_FINGER});
213 args += process(EV_KEY, BTN_TOOL_FINGER, 1);
214 args += process(EV_ABS, ABS_MT_POSITION_X, 50);
215 args += process(EV_ABS, ABS_MT_POSITION_Y, 50);
216 args += process(EV_ABS, ABS_MT_PRESSURE, 1);
217 args += process(EV_SYN, SYN_REPORT, 0);
218 ASSERT_THAT(args, testing::IsEmpty());
219
220 // Without this sleep, the test fails.
221 // TODO(b/284133337): Figure out whether this can be removed
222 std::this_thread::sleep_for(std::chrono::milliseconds(20));
223
224 args += process(EV_KEY, BTN_LEFT, 1);
225 setScanCodeState(KeyState::DOWN, {BTN_LEFT});
226 args += process(EV_SYN, SYN_REPORT, 0);
227
228 args += process(EV_KEY, BTN_LEFT, 0);
229 setScanCodeState(KeyState::UP, {BTN_LEFT});
230 args += process(EV_SYN, SYN_REPORT, 0);
231 ASSERT_THAT(args,
Harry Cutts379ea422023-12-21 15:31:47 +0000232 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_ENTER)),
233 VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE)),
234 VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_EXIT)),
Byoungho Jungee6268f2023-10-30 17:27:26 +0900235 VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_DOWN)),
236 VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_PRESS)),
237 VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
238 VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP)),
Harry Cutts379ea422023-12-21 15:31:47 +0000239 VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_ENTER))));
Byoungho Jungee6268f2023-10-30 17:27:26 +0900240
241 // Liftoff
242 args.clear();
243 args += process(EV_ABS, ABS_MT_PRESSURE, 0);
244 args += process(EV_ABS, ABS_MT_TRACKING_ID, -1);
245 args += process(EV_KEY, BTN_TOUCH, 0);
246 setScanCodeState(KeyState::UP, {BTN_TOOL_FINGER});
247 args += process(EV_KEY, BTN_TOOL_FINGER, 0);
248 args += process(EV_SYN, SYN_REPORT, 0);
249 ASSERT_THAT(args, testing::IsEmpty());
250}
251
Siarhei Vishniakou979f2d82023-05-16 14:26:24 -0700252} // namespace android