blob: be2e19e7df3bac9f29d0d6fe121ff7cb35d34a54 [file] [log] [blame]
Siarhei Vishniakou8588cc92018-12-12 18:17:58 -08001/*
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 "EventHub.h"
18
Prabir Pradhane0105c92019-12-26 12:32:13 -080019#include "UinputDevice.h"
20
Siarhei Vishniakou8588cc92018-12-12 18:17:58 -080021#include <gtest/gtest.h>
22#include <inttypes.h>
23#include <linux/uinput.h>
24#include <log/log.h>
25#include <chrono>
26
27#define TAG "EventHub_test"
28
Prabir Pradhane0105c92019-12-26 12:32:13 -080029using android::createUinputDevice;
Siarhei Vishniakou8588cc92018-12-12 18:17:58 -080030using android::EventHub;
31using android::EventHubInterface;
32using android::InputDeviceIdentifier;
33using android::RawEvent;
34using android::sp;
Prabir Pradhane0105c92019-12-26 12:32:13 -080035using android::UinputHomeKey;
Siarhei Vishniakou8588cc92018-12-12 18:17:58 -080036using std::chrono_literals::operator""ms;
37
38static constexpr bool DEBUG = false;
Siarhei Vishniakou8588cc92018-12-12 18:17:58 -080039
40static void dumpEvents(const std::vector<RawEvent>& events) {
41 for (const RawEvent& event : events) {
42 if (event.type >= EventHubInterface::FIRST_SYNTHETIC_EVENT) {
43 switch (event.type) {
44 case EventHubInterface::DEVICE_ADDED:
45 ALOGI("Device added: %i", event.deviceId);
46 break;
47 case EventHubInterface::DEVICE_REMOVED:
48 ALOGI("Device removed: %i", event.deviceId);
49 break;
50 case EventHubInterface::FINISHED_DEVICE_SCAN:
51 ALOGI("Finished device scan.");
52 break;
53 }
54 } else {
55 ALOGI("Device %" PRId32 " : time = %" PRId64 ", type %i, code %i, value %i",
56 event.deviceId, event.when, event.type, event.code, event.value);
57 }
58 }
59}
60
61// --- EventHubTest ---
62class EventHubTest : public testing::Test {
63protected:
64 std::unique_ptr<EventHubInterface> mEventHub;
65 // We are only going to emulate a single input device currently.
Prabir Pradhane0105c92019-12-26 12:32:13 -080066 std::unique_ptr<UinputHomeKey> mKeyboard;
Siarhei Vishniakou8588cc92018-12-12 18:17:58 -080067 int32_t mDeviceId;
Prabir Pradhane0105c92019-12-26 12:32:13 -080068
Siarhei Vishniakou8588cc92018-12-12 18:17:58 -080069 virtual void SetUp() override {
70 mEventHub = std::make_unique<EventHub>();
71 consumeInitialDeviceAddedEvents();
Prabir Pradhane0105c92019-12-26 12:32:13 -080072 mKeyboard = createUinputDevice<UinputHomeKey>();
Siarhei Vishniakou8588cc92018-12-12 18:17:58 -080073 mDeviceId = waitForDeviceCreation();
74 }
75 virtual void TearDown() override {
Prabir Pradhane0105c92019-12-26 12:32:13 -080076 mKeyboard.reset();
Siarhei Vishniakou8588cc92018-12-12 18:17:58 -080077 waitForDeviceClose(mDeviceId);
78 }
79
Siarhei Vishniakou8588cc92018-12-12 18:17:58 -080080 /**
81 * Return the device id of the created device.
82 */
83 int32_t waitForDeviceCreation();
84 void waitForDeviceClose(int32_t deviceId);
85 void consumeInitialDeviceAddedEvents();
Siarhei Vishniakou8588cc92018-12-12 18:17:58 -080086 std::vector<RawEvent> getEvents(std::chrono::milliseconds timeout = 5ms);
87};
88
89std::vector<RawEvent> EventHubTest::getEvents(std::chrono::milliseconds timeout) {
90 static constexpr size_t EVENT_BUFFER_SIZE = 256;
91 std::array<RawEvent, EVENT_BUFFER_SIZE> eventBuffer;
92 std::vector<RawEvent> events;
93
94 while (true) {
95 size_t count =
96 mEventHub->getEvents(timeout.count(), eventBuffer.data(), eventBuffer.size());
97 if (count == 0) {
98 break;
99 }
100 events.insert(events.end(), eventBuffer.begin(), eventBuffer.begin() + count);
101 }
102 if (DEBUG) {
103 dumpEvents(events);
104 }
105 return events;
106}
107
Siarhei Vishniakou8588cc92018-12-12 18:17:58 -0800108/**
109 * Since the test runs on a real platform, there will be existing devices
110 * in addition to the test devices being added. Therefore, when EventHub is first created,
111 * it will return a lot of "device added" type of events.
112 */
113void EventHubTest::consumeInitialDeviceAddedEvents() {
114 std::vector<RawEvent> events = getEvents(0ms);
115 std::set<int32_t /*deviceId*/> existingDevices;
116 // All of the events should be DEVICE_ADDED type, except the last one.
117 for (size_t i = 0; i < events.size() - 1; i++) {
118 const RawEvent& event = events[i];
119 EXPECT_EQ(EventHubInterface::DEVICE_ADDED, event.type);
120 existingDevices.insert(event.deviceId);
121 }
122 // None of the existing system devices should be changing while this test is run.
123 // Check that the returned device ids are unique for all of the existing devices.
124 EXPECT_EQ(existingDevices.size(), events.size() - 1);
125 // The last event should be "finished device scan"
126 EXPECT_EQ(EventHubInterface::FINISHED_DEVICE_SCAN, events[events.size() - 1].type);
127}
128
129int32_t EventHubTest::waitForDeviceCreation() {
130 // Wait a little longer than usual, to ensure input device has time to be created
131 std::vector<RawEvent> events = getEvents(20ms);
132 EXPECT_EQ(2U, events.size()); // Using "expect" because the function is non-void.
133 const RawEvent& deviceAddedEvent = events[0];
134 EXPECT_EQ(static_cast<int32_t>(EventHubInterface::DEVICE_ADDED), deviceAddedEvent.type);
135 InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceAddedEvent.deviceId);
136 const int32_t deviceId = deviceAddedEvent.deviceId;
Prabir Pradhane0105c92019-12-26 12:32:13 -0800137 EXPECT_EQ(identifier.name, mKeyboard->getName());
Siarhei Vishniakou8588cc92018-12-12 18:17:58 -0800138 const RawEvent& finishedDeviceScanEvent = events[1];
139 EXPECT_EQ(static_cast<int32_t>(EventHubInterface::FINISHED_DEVICE_SCAN),
140 finishedDeviceScanEvent.type);
141 return deviceId;
142}
143
144void EventHubTest::waitForDeviceClose(int32_t deviceId) {
145 std::vector<RawEvent> events = getEvents(20ms);
146 ASSERT_EQ(2U, events.size());
147 const RawEvent& deviceRemovedEvent = events[0];
148 EXPECT_EQ(static_cast<int32_t>(EventHubInterface::DEVICE_REMOVED), deviceRemovedEvent.type);
149 EXPECT_EQ(deviceId, deviceRemovedEvent.deviceId);
150 const RawEvent& finishedDeviceScanEvent = events[1];
151 EXPECT_EQ(static_cast<int32_t>(EventHubInterface::FINISHED_DEVICE_SCAN),
152 finishedDeviceScanEvent.type);
153}
154
Siarhei Vishniakou8588cc92018-12-12 18:17:58 -0800155/**
156 * Ensure that input_events are generated with monotonic clock.
157 * That means input_event should receive a timestamp that is in the future of the time
158 * before the event was sent.
159 * Input system uses CLOCK_MONOTONIC everywhere in the code base.
160 */
161TEST_F(EventHubTest, InputEvent_TimestampIsMonotonic) {
162 nsecs_t lastEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
Prabir Pradhane0105c92019-12-26 12:32:13 -0800163 ASSERT_NO_FATAL_FAILURE(mKeyboard->pressAndReleaseHomeKey());
Siarhei Vishniakou8588cc92018-12-12 18:17:58 -0800164
165 std::vector<RawEvent> events = getEvents();
166 ASSERT_EQ(4U, events.size()) << "Expected to receive 2 keys and 2 syncs, total of 4 events";
167 for (const RawEvent& event : events) {
168 // Cannot use strict comparison because the events may happen too quickly
169 ASSERT_LE(lastEventTime, event.when) << "Event must have occurred after the key was sent";
170 ASSERT_LT(std::chrono::nanoseconds(event.when - lastEventTime), 100ms)
171 << "Event times are too far apart";
172 lastEventTime = event.when; // Ensure all returned events are monotonic
173 }
174}