1 /*
2 * Copyright (C) 2019 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 #define LOG_TAG "input_classifier_hal_test"
18
19 #include <android-base/logging.h>
20 #include <android/hardware/input/classifier/1.0/IInputClassifier.h>
21 #include <android/hardware/input/common/1.0/types.h>
22 #include <gtest/gtest.h>
23 #include <hidl/GtestPrinter.h>
24 #include <hidl/ServiceManagement.h>
25 #include <input/InputDevice.h>
26 #include <unistd.h>
27
28 using ::android::ReservedInputDeviceId;
29 using ::android::sp;
30 using ::android::hardware::Return;
31 using ::android::hardware::input::classifier::V1_0::IInputClassifier;
32 using ::android::hardware::input::common::V1_0::Action;
33 using ::android::hardware::input::common::V1_0::Axis;
34 using ::android::hardware::input::common::V1_0::Button;
35 using ::android::hardware::input::common::V1_0::EdgeFlag;
36 using ::android::hardware::input::common::V1_0::MotionEvent;
37 using ::android::hardware::input::common::V1_0::PointerCoords;
38 using ::android::hardware::input::common::V1_0::PointerProperties;
39 using ::android::hardware::input::common::V1_0::Source;
40 using ::android::hardware::input::common::V1_0::ToolType;
41 using ::android::hardware::input::common::V1_0::VideoFrame;
42
getSimpleMotionEvent()43 static MotionEvent getSimpleMotionEvent() {
44 MotionEvent event;
45 event.action = Action::DOWN;
46 event.actionButton = Button::NONE;
47 event.actionIndex = 0;
48 event.buttonState = 0;
49 event.deviceId = 0;
50 event.deviceTimestamp = 0;
51 event.displayId = 1;
52 event.downTime = 2;
53 event.edgeFlags = 0;
54 event.eventTime = 3;
55 event.flags = 0;
56 event.frames = {};
57 event.metaState = 0;
58 event.policyFlags = 0;
59 event.source = Source::TOUCHSCREEN;
60 event.xPrecision = 0;
61 event.yPrecision = 0;
62
63 PointerCoords coords;
64 coords.bits = Axis::X | Axis::Y;
65 coords.values = {1 /*X*/, 2 /*Y*/};
66 event.pointerCoords = {coords};
67
68 PointerProperties properties;
69 properties.id = 0;
70 properties.toolType = ToolType::FINGER;
71 event.pointerProperties = {properties};
72
73 return event;
74 }
75
76 // The main test class for INPUT CLASSIFIER HIDL HAL 1.0.
77 class InputClassifierHidlTest_1_0 : public ::testing::TestWithParam<std::string> {
78 public:
SetUp()79 virtual void SetUp() override {
80 classifier = IInputClassifier::getService(GetParam());
81 ASSERT_NE(classifier, nullptr);
82 }
83
TearDown()84 virtual void TearDown() override {}
85
86 sp<IInputClassifier> classifier;
87 };
88
89 /**
90 * Call resetDevice(..) for a few common device id values, and make sure that the HAL
91 * can handle the resets gracefully.
92 */
TEST_P(InputClassifierHidlTest_1_0,ResetDevice)93 TEST_P(InputClassifierHidlTest_1_0, ResetDevice) {
94 EXPECT_TRUE(classifier->resetDevice(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID).isOk());
95 EXPECT_TRUE(classifier->resetDevice(ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID).isOk());
96 EXPECT_TRUE(classifier->resetDevice(1).isOk());
97 EXPECT_TRUE(classifier->resetDevice(2).isOk());
98 }
99
100 /**
101 * Call reset() on the HAL to ensure no fatal failure there.
102 */
TEST_P(InputClassifierHidlTest_1_0,ResetHal)103 TEST_P(InputClassifierHidlTest_1_0, ResetHal) {
104 EXPECT_TRUE(classifier->reset().isOk());
105 }
106
107 /**
108 * Classify an event without any video frames.
109 */
TEST_P(InputClassifierHidlTest_1_0,Classify_NoVideoFrame)110 TEST_P(InputClassifierHidlTest_1_0, Classify_NoVideoFrame) {
111 // Create a MotionEvent that does not have any video data
112 MotionEvent event = getSimpleMotionEvent();
113
114 EXPECT_TRUE(classifier->classify(event).isOk());
115 // We are not checking the actual classification here,
116 // because the HAL operation is highly device-specific.
117
118 // Return HAL to a consistent state by doing a reset
119 classifier->reset();
120 }
121
122 /**
123 * Classify an event with one video frame. Should be the most common scenario.
124 */
TEST_P(InputClassifierHidlTest_1_0,Classify_OneVideoFrame)125 TEST_P(InputClassifierHidlTest_1_0, Classify_OneVideoFrame) {
126 MotionEvent event = getSimpleMotionEvent();
127 VideoFrame frame;
128 frame.data = {1, 2, 3, 4};
129 frame.height = 2;
130 frame.width = 2;
131 frame.timestamp = event.eventTime;
132 event.frames = {frame};
133
134 EXPECT_TRUE(classifier->classify(event).isOk());
135 // We are not checking the actual classification here,
136 // because the HAL operation is highly device-specific.
137
138 // Return HAL to a consistent state by doing a reset
139 classifier->reset();
140 }
141
142 /**
143 * Classify an event with 2 video frames. This could happen if there's slowness in the system,
144 * or if simply the video rate is somehow higher that the input event rate.
145 * The HAL should be able to handle events with more than 1 video frame.
146 *
147 * The frames should be in chronological order, but it is not guaranteed that they will have
148 * monotonically increasing timestamps. Still, we provide consistent timestamps here since that
149 * is the most realistic mode of operation.
150 */
TEST_P(InputClassifierHidlTest_1_0,Classify_TwoVideoFrames)151 TEST_P(InputClassifierHidlTest_1_0, Classify_TwoVideoFrames) {
152 MotionEvent event = getSimpleMotionEvent();
153 VideoFrame frame1;
154 frame1.data = {1, 2, 3, 4};
155 frame1.height = 2;
156 frame1.width = 2;
157 frame1.timestamp = event.eventTime;
158 VideoFrame frame2 = frame1;
159 frame2.data = {5, 5, 5, -1};
160 frame2.timestamp += 1;
161 event.frames = {frame1, frame2};
162
163 EXPECT_TRUE(classifier->classify(event).isOk());
164 // We are not checking the actual classification here,
165 // because the HAL operation is highly device-specific.
166
167 // Return HAL to a consistent state by doing a reset
168 classifier->reset();
169 }
170
171 INSTANTIATE_TEST_SUITE_P(
172 PerInstance, InputClassifierHidlTest_1_0,
173 testing::ValuesIn(android::hardware::getAllHalInstanceNames(IInputClassifier::descriptor)),
174 android::hardware::PrintInstanceNameToString);
175