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 #include "../InputClassifier.h" 18 #include <gtest/gtest.h> 19 20 #include "TestInputListener.h" 21 22 #include <android/hardware/input/classifier/1.0/IInputClassifier.h> 23 24 using namespace android::hardware::input; 25 26 namespace android { 27 28 // --- InputClassifierTest --- 29 30 static NotifyMotionArgs generateBasicMotionArgs() { 31 // Create a basic motion event for testing 32 PointerProperties properties; 33 properties.id = 0; 34 properties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; 35 36 PointerCoords coords; 37 coords.clear(); 38 coords.setAxisValue(AMOTION_EVENT_AXIS_X, 1); 39 coords.setAxisValue(AMOTION_EVENT_AXIS_Y, 1); 40 static constexpr nsecs_t downTime = 2; 41 NotifyMotionArgs motionArgs(1/*sequenceNum*/, downTime/*eventTime*/, 3/*deviceId*/, 42 AINPUT_SOURCE_ANY, ADISPLAY_ID_DEFAULT, 4/*policyFlags*/, AMOTION_EVENT_ACTION_DOWN, 43 0/*actionButton*/, 0/*flags*/, AMETA_NONE, 0/*buttonState*/, MotionClassification::NONE, 44 AMOTION_EVENT_EDGE_FLAG_NONE, 5/*deviceTimestamp*/, 45 1/*pointerCount*/, &properties, &coords, 0/*xPrecision*/, 0/*yPrecision*/, 46 downTime, {}/*videoFrames*/); 47 return motionArgs; 48 } 49 50 class InputClassifierTest : public testing::Test { 51 protected: 52 sp<InputClassifierInterface> mClassifier; 53 sp<TestInputListener> mTestListener; 54 55 virtual void SetUp() override { 56 mTestListener = new TestInputListener(); 57 mClassifier = new InputClassifier(mTestListener); 58 } 59 60 virtual void TearDown() override { 61 mClassifier.clear(); 62 mTestListener.clear(); 63 } 64 }; 65 66 /** 67 * Create a basic configuration change and send it to input classifier. 68 * Expect that the event is received by the next input stage, unmodified. 69 */ 70 TEST_F(InputClassifierTest, SendToNextStage_NotifyConfigurationChangedArgs) { 71 // Create a basic configuration change and send to classifier 72 NotifyConfigurationChangedArgs args(1/*sequenceNum*/, 2/*eventTime*/); 73 74 mClassifier->notifyConfigurationChanged(&args); 75 NotifyConfigurationChangedArgs outArgs; 76 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled(&outArgs)); 77 ASSERT_EQ(args, outArgs); 78 } 79 80 TEST_F(InputClassifierTest, SendToNextStage_NotifyKeyArgs) { 81 // Create a basic key event and send to classifier 82 NotifyKeyArgs args(1/*sequenceNum*/, 2/*eventTime*/, 3/*deviceId*/, AINPUT_SOURCE_KEYBOARD, 83 ADISPLAY_ID_DEFAULT, 0/*policyFlags*/, AKEY_EVENT_ACTION_DOWN, 4/*flags*/, 84 AKEYCODE_HOME, 5/*scanCode*/, AMETA_NONE, 6/*downTime*/); 85 86 mClassifier->notifyKey(&args); 87 NotifyKeyArgs outArgs; 88 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&outArgs)); 89 ASSERT_EQ(args, outArgs); 90 } 91 92 93 /** 94 * Create a basic motion event and send it to input classifier. 95 * Expect that the event is received by the next input stage, unmodified. 96 */ 97 TEST_F(InputClassifierTest, SendToNextStage_NotifyMotionArgs) { 98 NotifyMotionArgs motionArgs = generateBasicMotionArgs(); 99 mClassifier->notifyMotion(&motionArgs); 100 NotifyMotionArgs args; 101 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args)); 102 ASSERT_EQ(motionArgs, args); 103 } 104 105 /** 106 * Create a basic switch event and send it to input classifier. 107 * Expect that the event is received by the next input stage, unmodified. 108 */ 109 TEST_F(InputClassifierTest, SendToNextStage_NotifySwitchArgs) { 110 NotifySwitchArgs args(1/*sequenceNum*/, 2/*eventTime*/, 3/*policyFlags*/, 4/*switchValues*/, 111 5/*switchMask*/); 112 113 mClassifier->notifySwitch(&args); 114 NotifySwitchArgs outArgs; 115 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifySwitchWasCalled(&outArgs)); 116 ASSERT_EQ(args, outArgs); 117 } 118 119 /** 120 * Create a basic device reset event and send it to input classifier. 121 * Expect that the event is received by the next input stage, unmodified. 122 */ 123 TEST_F(InputClassifierTest, SendToNextStage_NotifyDeviceResetArgs) { 124 NotifyDeviceResetArgs args(1/*sequenceNum*/, 2/*eventTime*/, 3/*deviceId*/); 125 126 mClassifier->notifyDeviceReset(&args); 127 NotifyDeviceResetArgs outArgs; 128 ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyDeviceResetWasCalled(&outArgs)); 129 ASSERT_EQ(args, outArgs); 130 } 131 132 // --- MotionClassifierTest --- 133 134 class MotionClassifierTest : public testing::Test { 135 protected: 136 std::unique_ptr<MotionClassifierInterface> mMotionClassifier; 137 138 virtual void SetUp() override { 139 mMotionClassifier = std::make_unique<MotionClassifier>(); 140 } 141 }; 142 143 /** 144 * Since MotionClassifier creates a new thread to communicate with HAL, 145 * it's not really expected to ever exit. However, for testing purposes, 146 * we need to ensure that it is able to exit cleanly. 147 * If the thread is not properly cleaned up, it will generate SIGABRT. 148 * The logic for exiting the thread and cleaning up the resources is inside 149 * the destructor. Here, we just make sure the destructor does not crash. 150 */ 151 TEST_F(MotionClassifierTest, Destructor_DoesNotCrash) { 152 mMotionClassifier = nullptr; 153 } 154 155 /** 156 * Make sure MotionClassifier can handle events that don't have any 157 * video frames. 158 */ 159 TEST_F(MotionClassifierTest, Classify_NoVideoFrames) { 160 NotifyMotionArgs motionArgs = generateBasicMotionArgs(); 161 162 // We are not checking the return value, because we can't be making assumptions 163 // about the HAL operation, since it will be highly hardware-dependent 164 ASSERT_NO_FATAL_FAILURE(mMotionClassifier->classify(motionArgs)); 165 } 166 167 /** 168 * Make sure nothing crashes when a videoFrame is sent. 169 */ 170 TEST_F(MotionClassifierTest, Classify_OneVideoFrame) { 171 NotifyMotionArgs motionArgs = generateBasicMotionArgs(); 172 173 std::vector<int16_t> videoData = {1, 2, 3, 4}; 174 timeval timestamp = { 1, 1}; 175 TouchVideoFrame frame(2, 2, std::move(videoData), timestamp); 176 motionArgs.videoFrames = {frame}; 177 178 // We are not checking the return value, because we can't be making assumptions 179 // about the HAL operation, since it will be highly hardware-dependent 180 ASSERT_NO_FATAL_FAILURE(mMotionClassifier->classify(motionArgs)); 181 } 182 183 /** 184 * Make sure nothing crashes when 2 videoFrames are sent. 185 */ 186 TEST_F(MotionClassifierTest, Classify_TwoVideoFrames) { 187 NotifyMotionArgs motionArgs = generateBasicMotionArgs(); 188 189 std::vector<int16_t> videoData1 = {1, 2, 3, 4}; 190 timeval timestamp1 = { 1, 1}; 191 TouchVideoFrame frame1(2, 2, std::move(videoData1), timestamp1); 192 193 std::vector<int16_t> videoData2 = {6, 6, 6, 6}; 194 timeval timestamp2 = { 1, 2}; 195 TouchVideoFrame frame2(2, 2, std::move(videoData2), timestamp2); 196 197 motionArgs.videoFrames = {frame1, frame2}; 198 199 // We are not checking the return value, because we can't be making assumptions 200 // about the HAL operation, since it will be highly hardware-dependent 201 ASSERT_NO_FATAL_FAILURE(mMotionClassifier->classify(motionArgs)); 202 } 203 204 /** 205 * Make sure MotionClassifier does not crash when it is reset. 206 */ 207 TEST_F(MotionClassifierTest, Reset_DoesNotCrash) { 208 ASSERT_NO_FATAL_FAILURE(mMotionClassifier->reset()); 209 } 210 211 /** 212 * Make sure MotionClassifier does not crash when a device is reset. 213 */ 214 TEST_F(MotionClassifierTest, DeviceReset_DoesNotCrash) { 215 NotifyDeviceResetArgs args(1/*sequenceNum*/, 2/*eventTime*/, 3/*deviceId*/); 216 ASSERT_NO_FATAL_FAILURE(mMotionClassifier->reset(args)); 217 } 218 219 } // namespace android 220