blob: 6606de896bd8072ff4364dd16925fc963ff18b15 [file] [log] [blame]
Siarhei Vishniakouf2652122021-03-05 21:39:46 +00001/*
2 * Copyright (C) 2021 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 "../dispatcher/LatencyTracker.h"
Asmita Poddardd9a6cd2023-09-26 15:35:12 +000018#include "../InputDeviceMetricsSource.h"
Siarhei Vishniakouf2652122021-03-05 21:39:46 +000019
Siarhei Vishniakou363e7292021-07-09 03:22:42 +000020#include <android-base/properties.h>
Siarhei Vishniakouf2652122021-03-05 21:39:46 +000021#include <binder/Binder.h>
22#include <gtest/gtest.h>
Asmita Poddardd9a6cd2023-09-26 15:35:12 +000023#include <gui/constants.h>
Siarhei Vishniakouf2652122021-03-05 21:39:46 +000024#include <inttypes.h>
Asmita Poddardd9a6cd2023-09-26 15:35:12 +000025#include <linux/input.h>
Siarhei Vishniakouf2652122021-03-05 21:39:46 +000026#include <log/log.h>
27
28#define TAG "LatencyTracker_test"
29
Siarhei Vishniakou363e7292021-07-09 03:22:42 +000030using android::base::HwTimeoutMultiplier;
Siarhei Vishniakouf2652122021-03-05 21:39:46 +000031using android::inputdispatcher::InputEventTimeline;
32using android::inputdispatcher::LatencyTracker;
33
34namespace android::inputdispatcher {
35
Asmita Poddardd9a6cd2023-09-26 15:35:12 +000036namespace {
37
38constexpr DeviceId DEVICE_ID = 100;
39
40static InputDeviceInfo generateTestDeviceInfo(uint16_t vendorId, uint16_t productId,
41 DeviceId deviceId) {
42 InputDeviceIdentifier identifier;
43 identifier.vendor = vendorId;
44 identifier.product = productId;
45 auto info = InputDeviceInfo();
46 info.initialize(deviceId, /*generation=*/1, /*controllerNumber=*/1, identifier, "Test Device",
47 /*isExternal=*/false, /*hasMic=*/false, ADISPLAY_ID_NONE);
48 return info;
49}
50
51void setDefaultInputDeviceInfo(LatencyTracker& tracker) {
52 InputDeviceInfo deviceInfo = generateTestDeviceInfo(
53 /*vendorId=*/0, /*productId=*/0, DEVICE_ID);
54 tracker.setInputDevices({deviceInfo});
55}
56
57} // namespace
58
Siarhei Vishniakou363e7292021-07-09 03:22:42 +000059const std::chrono::duration ANR_TIMEOUT = std::chrono::milliseconds(
60 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
61 HwTimeoutMultiplier());
62
Siarhei Vishniakouf2652122021-03-05 21:39:46 +000063InputEventTimeline getTestTimeline() {
64 InputEventTimeline t(
Harry Cutts33476232023-01-30 19:57:29 +000065 /*isDown=*/true,
66 /*eventTime=*/2,
Asmita Poddardd9a6cd2023-09-26 15:35:12 +000067 /*readTime=*/3,
68 /*vendorId=*/0,
69 /*productId=*/0,
70 /*sources=*/{InputDeviceUsageSource::UNKNOWN});
Harry Cutts33476232023-01-30 19:57:29 +000071 ConnectionTimeline expectedCT(/*deliveryTime=*/6, /*consumeTime=*/7, /*finishTime=*/8);
Siarhei Vishniakouf2652122021-03-05 21:39:46 +000072 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
73 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 9;
74 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 10;
75 expectedCT.setGraphicsTimeline(std::move(graphicsTimeline));
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070076 t.connectionTimelines.emplace(sp<BBinder>::make(), std::move(expectedCT));
Siarhei Vishniakouf2652122021-03-05 21:39:46 +000077 return t;
78}
79
80// --- LatencyTrackerTest ---
81class LatencyTrackerTest : public testing::Test, public InputEventTimelineProcessor {
82protected:
83 std::unique_ptr<LatencyTracker> mTracker;
84 sp<IBinder> connection1;
85 sp<IBinder> connection2;
86
87 void SetUp() override {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070088 connection1 = sp<BBinder>::make();
89 connection2 = sp<BBinder>::make();
Siarhei Vishniakouf2652122021-03-05 21:39:46 +000090
91 mTracker = std::make_unique<LatencyTracker>(this);
Asmita Poddardd9a6cd2023-09-26 15:35:12 +000092 setDefaultInputDeviceInfo(*mTracker);
Siarhei Vishniakouf2652122021-03-05 21:39:46 +000093 }
94 void TearDown() override {}
95
Siarhei Vishniakou363e7292021-07-09 03:22:42 +000096 void triggerEventReporting(nsecs_t lastEventTime);
97
Siarhei Vishniakouf2652122021-03-05 21:39:46 +000098 void assertReceivedTimeline(const InputEventTimeline& timeline);
99 /**
100 * Timelines can be received in any order (order is not guaranteed). So if we are expecting more
101 * than 1 timeline, use this function to check that the set of received timelines matches
102 * what we expected.
103 */
104 void assertReceivedTimelines(const std::vector<InputEventTimeline>& timelines);
105
106private:
107 void processTimeline(const InputEventTimeline& timeline) override {
108 mReceivedTimelines.push_back(timeline);
109 }
110 std::deque<InputEventTimeline> mReceivedTimelines;
111};
112
Siarhei Vishniakou363e7292021-07-09 03:22:42 +0000113/**
114 * Send an event that would trigger the reporting of all of the events that are at least as old as
115 * the provided 'lastEventTime'.
116 */
117void LatencyTrackerTest::triggerEventReporting(nsecs_t lastEventTime) {
118 const nsecs_t triggerEventTime =
119 lastEventTime + std::chrono::nanoseconds(ANR_TIMEOUT).count() + 1;
Harry Cutts33476232023-01-30 19:57:29 +0000120 mTracker->trackListener(/*inputEventId=*/1, /*isDown=*/true, triggerEventTime,
Asmita Poddardd9a6cd2023-09-26 15:35:12 +0000121 /*readTime=*/3, DEVICE_ID,
122 /*sources=*/{InputDeviceUsageSource::UNKNOWN});
Siarhei Vishniakou363e7292021-07-09 03:22:42 +0000123}
124
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000125void LatencyTrackerTest::assertReceivedTimeline(const InputEventTimeline& timeline) {
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000126 ASSERT_FALSE(mReceivedTimelines.empty());
127 const InputEventTimeline& t = mReceivedTimelines.front();
128 ASSERT_EQ(timeline, t);
129 mReceivedTimelines.pop_front();
130}
131
132/**
133 * We are essentially comparing two multisets, but without constructing them.
134 * This comparison is inefficient, but it avoids having to construct a set, and also avoids the
135 * declaration of copy constructor for ConnectionTimeline.
136 * We ensure that collections A and B have the same size, that for every element in A, there is an
137 * equal element in B, and for every element in B there is an equal element in A.
138 */
139void LatencyTrackerTest::assertReceivedTimelines(const std::vector<InputEventTimeline>& timelines) {
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000140 ASSERT_EQ(timelines.size(), mReceivedTimelines.size());
141 for (const InputEventTimeline& expectedTimeline : timelines) {
142 bool found = false;
143 for (const InputEventTimeline& receivedTimeline : mReceivedTimelines) {
144 if (receivedTimeline == expectedTimeline) {
145 found = true;
146 break;
147 }
148 }
149 ASSERT_TRUE(found) << "Could not find expected timeline with eventTime="
150 << expectedTimeline.eventTime;
151 }
152 for (const InputEventTimeline& receivedTimeline : mReceivedTimelines) {
153 bool found = false;
154 for (const InputEventTimeline& expectedTimeline : timelines) {
155 if (receivedTimeline == expectedTimeline) {
156 found = true;
157 break;
158 }
159 }
160 ASSERT_TRUE(found) << "Could not find received timeline with eventTime="
161 << receivedTimeline.eventTime;
162 }
163 mReceivedTimelines.clear();
164}
165
166/**
167 * Ensure that calling 'trackListener' in isolation only creates an inputflinger timeline, without
168 * any additional ConnectionTimeline's.
169 */
170TEST_F(LatencyTrackerTest, TrackListener_DoesNotTriggerReporting) {
Harry Cutts33476232023-01-30 19:57:29 +0000171 mTracker->trackListener(/*inputEventId=*/1, /*isDown=*/false, /*eventTime=*/2,
Asmita Poddardd9a6cd2023-09-26 15:35:12 +0000172 /*readTime=*/3, DEVICE_ID, {InputDeviceUsageSource::UNKNOWN});
Harry Cutts33476232023-01-30 19:57:29 +0000173 triggerEventReporting(/*eventTime=*/2);
Asmita Poddardd9a6cd2023-09-26 15:35:12 +0000174 assertReceivedTimeline(InputEventTimeline{/*isDown=*/false, /*eventTime=*/2,
175 /*readTime=*/3, /*vendorId=*/0, /*productID=*/0,
176 /*sources=*/{InputDeviceUsageSource::UNKNOWN}});
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000177}
178
179/**
180 * A single call to trackFinishedEvent should not cause a timeline to be reported.
181 */
182TEST_F(LatencyTrackerTest, TrackFinishedEvent_DoesNotTriggerReporting) {
Harry Cutts33476232023-01-30 19:57:29 +0000183 mTracker->trackFinishedEvent(/*inputEventId=*/1, connection1, /*deliveryTime=*/2,
184 /*consumeTime=*/3, /*finishTime=*/4);
185 triggerEventReporting(/*eventTime=*/4);
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000186 assertReceivedTimelines({});
187}
188
189/**
190 * A single call to trackGraphicsLatency should not cause a timeline to be reported.
191 */
192TEST_F(LatencyTrackerTest, TrackGraphicsLatency_DoesNotTriggerReporting) {
193 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
194 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
195 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
Harry Cutts33476232023-01-30 19:57:29 +0000196 mTracker->trackGraphicsLatency(/*inputEventId=*/1, connection2, graphicsTimeline);
197 triggerEventReporting(/*eventTime=*/3);
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000198 assertReceivedTimelines({});
199}
200
201TEST_F(LatencyTrackerTest, TrackAllParameters_ReportsFullTimeline) {
202 constexpr int32_t inputEventId = 1;
203 InputEventTimeline expected = getTestTimeline();
204
205 const auto& [connectionToken, expectedCT] = *expected.connectionTimelines.begin();
206
Asmita Poddardd9a6cd2023-09-26 15:35:12 +0000207 mTracker->trackListener(inputEventId, expected.isDown, expected.eventTime, expected.readTime,
208 DEVICE_ID, {InputDeviceUsageSource::UNKNOWN});
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000209 mTracker->trackFinishedEvent(inputEventId, connectionToken, expectedCT.deliveryTime,
210 expectedCT.consumeTime, expectedCT.finishTime);
211 mTracker->trackGraphicsLatency(inputEventId, connectionToken, expectedCT.graphicsTimeline);
212
Siarhei Vishniakou363e7292021-07-09 03:22:42 +0000213 triggerEventReporting(expected.eventTime);
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000214 assertReceivedTimeline(expected);
215}
216
Siarhei Vishniakou363e7292021-07-09 03:22:42 +0000217/**
218 * Send 2 events with the same inputEventId, but different eventTime's. Ensure that no crash occurs,
219 * and that the tracker drops such events completely.
220 */
221TEST_F(LatencyTrackerTest, WhenDuplicateEventsAreReported_DoesNotCrash) {
222 constexpr nsecs_t inputEventId = 1;
223 constexpr nsecs_t readTime = 3; // does not matter for this test
224 constexpr bool isDown = true; // does not matter for this test
225
226 // In the following 2 calls to trackListener, the inputEventId's are the same, but event times
227 // are different.
Asmita Poddardd9a6cd2023-09-26 15:35:12 +0000228 mTracker->trackListener(inputEventId, isDown, /*eventTime=*/1, readTime, DEVICE_ID,
229 {InputDeviceUsageSource::UNKNOWN});
230 mTracker->trackListener(inputEventId, isDown, /*eventTime=*/2, readTime, DEVICE_ID,
231 {InputDeviceUsageSource::UNKNOWN});
Siarhei Vishniakou363e7292021-07-09 03:22:42 +0000232
Harry Cutts33476232023-01-30 19:57:29 +0000233 triggerEventReporting(/*eventTime=*/2);
Siarhei Vishniakou363e7292021-07-09 03:22:42 +0000234 // Since we sent duplicate input events, the tracker should just delete all of them, because it
235 // does not have enough information to properly track them.
236 assertReceivedTimelines({});
237}
238
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000239TEST_F(LatencyTrackerTest, MultipleEvents_AreReportedConsistently) {
240 constexpr int32_t inputEventId1 = 1;
241 InputEventTimeline timeline1(
242 /*isDown*/ true,
243 /*eventTime*/ 2,
Asmita Poddardd9a6cd2023-09-26 15:35:12 +0000244 /*readTime*/ 3,
245 /*vendorId=*/0,
246 /*productId=*/0,
247 /*sources=*/{InputDeviceUsageSource::UNKNOWN});
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000248 timeline1.connectionTimelines.emplace(connection1,
249 ConnectionTimeline(/*deliveryTime*/ 6, /*consumeTime*/ 7,
250 /*finishTime*/ 8));
251 ConnectionTimeline& connectionTimeline1 = timeline1.connectionTimelines.begin()->second;
252 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline1;
253 graphicsTimeline1[GraphicsTimeline::GPU_COMPLETED_TIME] = 9;
254 graphicsTimeline1[GraphicsTimeline::PRESENT_TIME] = 10;
255 connectionTimeline1.setGraphicsTimeline(std::move(graphicsTimeline1));
256
257 constexpr int32_t inputEventId2 = 10;
258 InputEventTimeline timeline2(
Harry Cutts33476232023-01-30 19:57:29 +0000259 /*isDown=*/false,
260 /*eventTime=*/20,
Asmita Poddardd9a6cd2023-09-26 15:35:12 +0000261 /*readTime=*/30,
262 /*vendorId=*/0,
263 /*productId=*/0,
264 /*sources=*/{InputDeviceUsageSource::UNKNOWN});
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000265 timeline2.connectionTimelines.emplace(connection2,
Harry Cutts33476232023-01-30 19:57:29 +0000266 ConnectionTimeline(/*deliveryTime=*/60,
267 /*consumeTime=*/70,
268 /*finishTime=*/80));
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000269 ConnectionTimeline& connectionTimeline2 = timeline2.connectionTimelines.begin()->second;
270 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline2;
271 graphicsTimeline2[GraphicsTimeline::GPU_COMPLETED_TIME] = 90;
272 graphicsTimeline2[GraphicsTimeline::PRESENT_TIME] = 100;
273 connectionTimeline2.setGraphicsTimeline(std::move(graphicsTimeline2));
274
275 // Start processing first event
276 mTracker->trackListener(inputEventId1, timeline1.isDown, timeline1.eventTime,
Asmita Poddardd9a6cd2023-09-26 15:35:12 +0000277 timeline1.readTime, DEVICE_ID, {InputDeviceUsageSource::UNKNOWN});
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000278 // Start processing second event
279 mTracker->trackListener(inputEventId2, timeline2.isDown, timeline2.eventTime,
Asmita Poddardd9a6cd2023-09-26 15:35:12 +0000280 timeline2.readTime, DEVICE_ID, {InputDeviceUsageSource::UNKNOWN});
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000281 mTracker->trackFinishedEvent(inputEventId1, connection1, connectionTimeline1.deliveryTime,
282 connectionTimeline1.consumeTime, connectionTimeline1.finishTime);
283
284 mTracker->trackFinishedEvent(inputEventId2, connection2, connectionTimeline2.deliveryTime,
285 connectionTimeline2.consumeTime, connectionTimeline2.finishTime);
286 mTracker->trackGraphicsLatency(inputEventId1, connection1,
287 connectionTimeline1.graphicsTimeline);
288 mTracker->trackGraphicsLatency(inputEventId2, connection2,
289 connectionTimeline2.graphicsTimeline);
290 // Now both events should be completed
Siarhei Vishniakou363e7292021-07-09 03:22:42 +0000291 triggerEventReporting(timeline2.eventTime);
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000292 assertReceivedTimelines({timeline1, timeline2});
293}
294
295/**
296 * Check that LatencyTracker consistently tracks events even if there are many incomplete events.
297 */
298TEST_F(LatencyTrackerTest, IncompleteEvents_AreHandledConsistently) {
299 InputEventTimeline timeline = getTestTimeline();
300 std::vector<InputEventTimeline> expectedTimelines;
301 const ConnectionTimeline& expectedCT = timeline.connectionTimelines.begin()->second;
302 const sp<IBinder>& token = timeline.connectionTimelines.begin()->first;
303
304 for (size_t i = 1; i <= 100; i++) {
Harry Cutts33476232023-01-30 19:57:29 +0000305 mTracker->trackListener(/*inputEventId=*/i, timeline.isDown, timeline.eventTime,
Asmita Poddardd9a6cd2023-09-26 15:35:12 +0000306 timeline.readTime, /*deviceId=*/DEVICE_ID,
307 /*sources=*/{InputDeviceUsageSource::UNKNOWN});
308 expectedTimelines.push_back(InputEventTimeline{timeline.isDown, timeline.eventTime,
309 timeline.readTime, timeline.vendorId,
310 timeline.productId, timeline.sources});
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000311 }
312 // Now, complete the first event that was sent.
Harry Cutts33476232023-01-30 19:57:29 +0000313 mTracker->trackFinishedEvent(/*inputEventId=*/1, token, expectedCT.deliveryTime,
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000314 expectedCT.consumeTime, expectedCT.finishTime);
Harry Cutts33476232023-01-30 19:57:29 +0000315 mTracker->trackGraphicsLatency(/*inputEventId=*/1, token, expectedCT.graphicsTimeline);
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000316
317 expectedTimelines[0].connectionTimelines.emplace(token, std::move(expectedCT));
Siarhei Vishniakou363e7292021-07-09 03:22:42 +0000318 triggerEventReporting(timeline.eventTime);
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000319 assertReceivedTimelines(expectedTimelines);
320}
321
322/**
323 * For simplicity of the implementation, LatencyTracker only starts tracking an event when
324 * 'trackListener' is invoked.
325 * Both 'trackFinishedEvent' and 'trackGraphicsLatency' should not start a new event.
326 * If they are received before 'trackListener' (which should not be possible), they are ignored.
327 */
328TEST_F(LatencyTrackerTest, EventsAreTracked_WhenTrackListenerIsCalledFirst) {
329 constexpr int32_t inputEventId = 1;
330 InputEventTimeline expected = getTestTimeline();
331 const ConnectionTimeline& expectedCT = expected.connectionTimelines.begin()->second;
332 mTracker->trackFinishedEvent(inputEventId, connection1, expectedCT.deliveryTime,
333 expectedCT.consumeTime, expectedCT.finishTime);
334 mTracker->trackGraphicsLatency(inputEventId, connection1, expectedCT.graphicsTimeline);
335
Asmita Poddardd9a6cd2023-09-26 15:35:12 +0000336 mTracker->trackListener(inputEventId, expected.isDown, expected.eventTime, expected.readTime,
337 DEVICE_ID, {InputDeviceUsageSource::UNKNOWN});
Siarhei Vishniakou363e7292021-07-09 03:22:42 +0000338 triggerEventReporting(expected.eventTime);
Asmita Poddardd9a6cd2023-09-26 15:35:12 +0000339 assertReceivedTimeline(InputEventTimeline{expected.isDown, expected.eventTime,
340 expected.readTime, expected.vendorId,
341 expected.productId, expected.sources});
342}
343
344/**
345 * Check that LatencyTracker has the received timeline that contains the correctly
346 * resolved product ID, vendor ID and source for a particular device ID from
347 * among a list of devices.
348 */
349TEST_F(LatencyTrackerTest, TrackListenerCheck_DeviceInfoFieldsInputEventTimeline) {
350 constexpr int32_t inputEventId = 1;
351 InputEventTimeline timeline(
352 /*isDown*/ true, /*eventTime*/ 2, /*readTime*/ 3,
353 /*vendorId=*/50, /*productId=*/60,
354 /*sources=*/
355 {InputDeviceUsageSource::TOUCHSCREEN, InputDeviceUsageSource::STYLUS_DIRECT});
356 InputDeviceInfo deviceInfo1 = generateTestDeviceInfo(
357 /*vendorId=*/5, /*productId=*/6, /*deviceId=*/DEVICE_ID + 1);
358 InputDeviceInfo deviceInfo2 = generateTestDeviceInfo(
359 /*vendorId=*/50, /*productId=*/60, /*deviceId=*/DEVICE_ID);
360
361 mTracker->setInputDevices({deviceInfo1, deviceInfo2});
362 mTracker->trackListener(inputEventId, timeline.isDown, timeline.eventTime, timeline.readTime,
363 DEVICE_ID,
364 {InputDeviceUsageSource::TOUCHSCREEN,
365 InputDeviceUsageSource::STYLUS_DIRECT});
366 triggerEventReporting(timeline.eventTime);
367 assertReceivedTimeline(timeline);
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000368}
369
370} // namespace android::inputdispatcher