1 /*
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 
22 #include <thread>
23 #include "InputMapperTest.h"
24 #include "InterfaceMocks.h"
25 #include "TestEventMatchers.h"
26 
27 #define TAG "TouchpadInputMapper_test"
28 
29 namespace android {
30 
31 using testing::Return;
32 using testing::VariantWith;
33 constexpr auto ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
34 constexpr auto ACTION_UP = AMOTION_EVENT_ACTION_UP;
35 constexpr auto BUTTON_PRESS = AMOTION_EVENT_ACTION_BUTTON_PRESS;
36 constexpr auto BUTTON_RELEASE = AMOTION_EVENT_ACTION_BUTTON_RELEASE;
37 constexpr auto HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
38 constexpr auto HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
39 constexpr auto HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
40 constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
41 constexpr int32_t DISPLAY_WIDTH = 480;
42 constexpr int32_t DISPLAY_HEIGHT = 800;
43 constexpr std::optional<uint8_t> NO_PORT = std::nullopt; // no physical port is specified
44 
45 /**
46  * Unit tests for TouchpadInputMapper.
47  */
48 class TouchpadInputMapperTest : public InputMapperUnitTest {
49 protected:
SetUp()50     void SetUp() override {
51         InputMapperUnitTest::SetUp();
52 
53         // Present scan codes: BTN_TOUCH and BTN_TOOL_FINGER
54         expectScanCodes(/*present=*/true,
55                         {BTN_LEFT, BTN_RIGHT, BTN_TOOL_FINGER, BTN_TOOL_QUINTTAP, BTN_TOUCH,
56                          BTN_TOOL_DOUBLETAP, BTN_TOOL_TRIPLETAP, BTN_TOOL_QUADTAP});
57         // Missing scan codes that the mapper checks for.
58         expectScanCodes(/*present=*/false,
59                         {BTN_TOOL_PEN, BTN_TOOL_RUBBER, BTN_TOOL_BRUSH, BTN_TOOL_PENCIL,
60                          BTN_TOOL_AIRBRUSH});
61 
62         // Current scan code state - all keys are UP by default
63         setScanCodeState(KeyState::UP, {BTN_TOUCH,          BTN_STYLUS,
64                                         BTN_STYLUS2,        BTN_0,
65                                         BTN_TOOL_FINGER,    BTN_TOOL_PEN,
66                                         BTN_TOOL_RUBBER,    BTN_TOOL_BRUSH,
67                                         BTN_TOOL_PENCIL,    BTN_TOOL_AIRBRUSH,
68                                         BTN_TOOL_MOUSE,     BTN_TOOL_LENS,
69                                         BTN_TOOL_DOUBLETAP, BTN_TOOL_TRIPLETAP,
70                                         BTN_TOOL_QUADTAP,   BTN_TOOL_QUINTTAP,
71                                         BTN_LEFT,           BTN_RIGHT,
72                                         BTN_MIDDLE,         BTN_BACK,
73                                         BTN_SIDE,           BTN_FORWARD,
74                                         BTN_EXTRA,          BTN_TASK});
75 
76         setKeyCodeState(KeyState::UP,
77                         {AKEYCODE_STYLUS_BUTTON_PRIMARY, AKEYCODE_STYLUS_BUTTON_SECONDARY});
78 
79         // Key mappings
80         EXPECT_CALL(mMockEventHub,
81                     mapKey(EVENTHUB_ID, BTN_LEFT, /*usageCode=*/0, /*metaState=*/0, testing::_,
82                            testing::_, testing::_))
83                 .WillRepeatedly(Return(NAME_NOT_FOUND));
84 
85         // Input properties - only INPUT_PROP_BUTTONPAD
86         EXPECT_CALL(mMockEventHub, hasInputProperty(EVENTHUB_ID, INPUT_PROP_BUTTONPAD))
87                 .WillRepeatedly(Return(true));
88         EXPECT_CALL(mMockEventHub, hasInputProperty(EVENTHUB_ID, INPUT_PROP_SEMI_MT))
89                 .WillRepeatedly(Return(false));
90 
91         // Axes that the device has
92         setupAxis(ABS_MT_SLOT, /*valid=*/true, /*min=*/0, /*max=*/4, /*resolution=*/0);
93         setupAxis(ABS_MT_POSITION_X, /*valid=*/true, /*min=*/0, /*max=*/2000, /*resolution=*/24);
94         setupAxis(ABS_MT_POSITION_Y, /*valid=*/true, /*min=*/0, /*max=*/1000, /*resolution=*/24);
95         setupAxis(ABS_MT_PRESSURE, /*valid=*/true, /*min*/ 0, /*max=*/255, /*resolution=*/0);
96         // Axes that the device does not have
97         setupAxis(ABS_MT_ORIENTATION, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0);
98         setupAxis(ABS_MT_TOUCH_MAJOR, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0);
99         setupAxis(ABS_MT_TOUCH_MINOR, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0);
100         setupAxis(ABS_MT_WIDTH_MAJOR, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0);
101         setupAxis(ABS_MT_WIDTH_MINOR, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0);
102         setupAxis(ABS_MT_TRACKING_ID, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0);
103         setupAxis(ABS_MT_DISTANCE, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0);
104         setupAxis(ABS_MT_TOOL_TYPE, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0);
105 
106         EXPECT_CALL(mMockEventHub, getAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT, testing::_))
107                 .WillRepeatedly([](int32_t eventHubId, int32_t, int32_t* outValue) {
108                     *outValue = 0;
109                     return OK;
110                 });
111         EXPECT_CALL(mMockEventHub, getMtSlotValues(EVENTHUB_ID, testing::_, testing::_))
112                 .WillRepeatedly([]() -> base::Result<std::vector<int32_t>> {
113                     return base::ResultError("Axis not supported", NAME_NOT_FOUND);
114                 });
115         createDevice();
116         mMapper = createInputMapper<TouchpadInputMapper>(*mDeviceContext, mReaderConfiguration);
117     }
118 };
119 
120 /**
121  * Start moving the finger and then click the left touchpad button. Check whether HOVER_EXIT is
122  * generated when hovering stops. Currently, it is not.
123  * In the current implementation, HOVER_MOVE and ACTION_DOWN events are not sent out right away,
124  * but only after the button is released.
125  */
TEST_F(TouchpadInputMapperTest,HoverAndLeftButtonPress)126 TEST_F(TouchpadInputMapperTest, HoverAndLeftButtonPress) {
127     mFakePolicy->setDefaultPointerDisplayId(DISPLAY_ID);
128     mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
129                                     /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL);
130 
131     std::list<NotifyArgs> args;
132 
133     args += mMapper->reconfigure(systemTime(SYSTEM_TIME_MONOTONIC), mReaderConfiguration,
134                                  InputReaderConfiguration::Change::DISPLAY_INFO);
135     ASSERT_THAT(args, testing::IsEmpty());
136 
137     args += process(EV_ABS, ABS_MT_TRACKING_ID, 1);
138     args += process(EV_KEY, BTN_TOUCH, 1);
139     setScanCodeState(KeyState::DOWN, {BTN_TOOL_FINGER});
140     args += process(EV_KEY, BTN_TOOL_FINGER, 1);
141     args += process(EV_ABS, ABS_MT_POSITION_X, 50);
142     args += process(EV_ABS, ABS_MT_POSITION_Y, 50);
143     args += process(EV_ABS, ABS_MT_PRESSURE, 1);
144     args += process(EV_SYN, SYN_REPORT, 0);
145     ASSERT_THAT(args, testing::IsEmpty());
146 
147     // Without this sleep, the test fails.
148     // TODO(b/284133337): Figure out whether this can be removed
149     std::this_thread::sleep_for(std::chrono::milliseconds(20));
150 
151     args += process(EV_KEY, BTN_LEFT, 1);
152     setScanCodeState(KeyState::DOWN, {BTN_LEFT});
153     args += process(EV_SYN, SYN_REPORT, 0);
154 
155     args += process(EV_KEY, BTN_LEFT, 0);
156     setScanCodeState(KeyState::UP, {BTN_LEFT});
157     args += process(EV_SYN, SYN_REPORT, 0);
158     ASSERT_THAT(args,
159                 ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_ENTER)),
160                             VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE)),
161                             VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_EXIT)),
162                             VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_DOWN)),
163                             VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_PRESS)),
164                             VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
165                             VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP)),
166                             VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_ENTER))));
167 
168     // Liftoff
169     args.clear();
170     args += process(EV_ABS, ABS_MT_PRESSURE, 0);
171     args += process(EV_ABS, ABS_MT_TRACKING_ID, -1);
172     args += process(EV_KEY, BTN_TOUCH, 0);
173     setScanCodeState(KeyState::UP, {BTN_TOOL_FINGER});
174     args += process(EV_KEY, BTN_TOOL_FINGER, 0);
175     args += process(EV_SYN, SYN_REPORT, 0);
176     ASSERT_THAT(args, testing::IsEmpty());
177 }
178 
179 } // namespace android
180