blob: ca0f1e899998abb336720dd8f1c780bfd4a33b7d [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 Vishniakou93ee5402024-10-09 00:07:23 +000019#include "NotifyArgsBuilders.h"
20#include "android/input.h"
Siarhei Vishniakouf2652122021-03-05 21:39:46 +000021
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +000022#include <android-base/logging.h>
Siarhei Vishniakou363e7292021-07-09 03:22:42 +000023#include <android-base/properties.h>
Siarhei Vishniakouf2652122021-03-05 21:39:46 +000024#include <binder/Binder.h>
25#include <gtest/gtest.h>
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +000026#include <input/PrintTools.h>
Siarhei Vishniakouf2652122021-03-05 21:39:46 +000027#include <inttypes.h>
Asmita Poddardd9a6cd2023-09-26 15:35:12 +000028#include <linux/input.h>
Siarhei Vishniakouf2652122021-03-05 21:39:46 +000029#include <log/log.h>
30
31#define TAG "LatencyTracker_test"
32
Siarhei Vishniakou363e7292021-07-09 03:22:42 +000033using android::base::HwTimeoutMultiplier;
Siarhei Vishniakouf2652122021-03-05 21:39:46 +000034using android::inputdispatcher::InputEventTimeline;
35using android::inputdispatcher::LatencyTracker;
36
37namespace android::inputdispatcher {
38
Asmita Poddardd9a6cd2023-09-26 15:35:12 +000039namespace {
40
41constexpr DeviceId DEVICE_ID = 100;
42
43static InputDeviceInfo generateTestDeviceInfo(uint16_t vendorId, uint16_t productId,
44 DeviceId deviceId) {
45 InputDeviceIdentifier identifier;
46 identifier.vendor = vendorId;
47 identifier.product = productId;
48 auto info = InputDeviceInfo();
49 info.initialize(deviceId, /*generation=*/1, /*controllerNumber=*/1, identifier, "Test Device",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070050 /*isExternal=*/false, /*hasMic=*/false, ui::LogicalDisplayId::INVALID);
Asmita Poddardd9a6cd2023-09-26 15:35:12 +000051 return info;
52}
53
54void setDefaultInputDeviceInfo(LatencyTracker& tracker) {
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +000055 InputDeviceInfo deviceInfo = generateTestDeviceInfo(/*vendorId=*/0, /*productId=*/0, DEVICE_ID);
Asmita Poddardd9a6cd2023-09-26 15:35:12 +000056 tracker.setInputDevices({deviceInfo});
57}
58
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +000059const auto FIRST_TOUCH_POINTER = PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200);
60
61/**
62 * This is a convenience method for comparing timelines that also prints the difference between
63 * the two structures. This helps debugging when the timelines don't match.
64 * @param received the timeline that was actually received
65 * @param expected the timeline that we expected to receive
66 * @return true if the two timelines match, false otherwise.
67 */
68bool timelinesAreEqual(const InputEventTimeline& received, const InputEventTimeline& expected) {
69 LOG_IF(ERROR, expected.eventTime != received.eventTime)
70 << "Received timeline with eventTime=" << received.eventTime
71 << " instead of expected eventTime=" << expected.eventTime;
72 LOG_IF(ERROR, expected.readTime != received.readTime)
73 << "Received timeline with readTime=" << received.readTime
74 << " instead of expected readTime=" << expected.readTime;
75 LOG_IF(ERROR, expected.vendorId != received.vendorId)
76 << "Received timeline with vendorId=" << received.vendorId
77 << " instead of expected vendorId=" << expected.vendorId;
78 LOG_IF(ERROR, expected.productId != received.productId)
79 << "Received timeline with productId=" << received.productId
80 << " instead of expected productId=" << expected.productId;
81 LOG_IF(ERROR, expected.sources != received.sources)
82 << "Received timeline with sources=" << dumpSet(received.sources, ftl::enum_string)
83 << " instead of expected sources=" << dumpSet(expected.sources, ftl::enum_string);
84 LOG_IF(ERROR, expected.inputEventActionType != received.inputEventActionType)
85 << "Received timeline with inputEventActionType="
86 << ftl::enum_string(received.inputEventActionType)
87 << " instead of expected inputEventActionType="
88 << ftl::enum_string(expected.inputEventActionType);
89
90 return received == expected;
91}
92
Asmita Poddardd9a6cd2023-09-26 15:35:12 +000093} // namespace
94
Siarhei Vishniakou363e7292021-07-09 03:22:42 +000095const std::chrono::duration ANR_TIMEOUT = std::chrono::milliseconds(
96 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
97 HwTimeoutMultiplier());
98
Siarhei Vishniakouf2652122021-03-05 21:39:46 +000099InputEventTimeline getTestTimeline() {
100 InputEventTimeline t(
Harry Cutts33476232023-01-30 19:57:29 +0000101 /*eventTime=*/2,
Asmita Poddardd9a6cd2023-09-26 15:35:12 +0000102 /*readTime=*/3,
103 /*vendorId=*/0,
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000104 /*productId=*/0, {InputDeviceUsageSource::TOUCHSCREEN},
jioana0bdbea12024-08-10 19:26:04 +0000105 /*inputEventActionType=*/InputEventActionType::UNKNOWN_INPUT_EVENT);
Harry Cutts33476232023-01-30 19:57:29 +0000106 ConnectionTimeline expectedCT(/*deliveryTime=*/6, /*consumeTime=*/7, /*finishTime=*/8);
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000107 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline{};
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000108 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 9;
109 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 10;
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000110 expectedCT.setGraphicsTimeline(graphicsTimeline);
111 t.connectionTimelines.emplace(sp<BBinder>::make(), expectedCT);
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000112 return t;
113}
114
115// --- LatencyTrackerTest ---
116class LatencyTrackerTest : public testing::Test, public InputEventTimelineProcessor {
117protected:
118 std::unique_ptr<LatencyTracker> mTracker;
119 sp<IBinder> connection1;
120 sp<IBinder> connection2;
121
122 void SetUp() override {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700123 connection1 = sp<BBinder>::make();
124 connection2 = sp<BBinder>::make();
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000125
jioana24878b52024-09-10 10:13:27 +0000126 mTracker = std::make_unique<LatencyTracker>(*this);
Asmita Poddardd9a6cd2023-09-26 15:35:12 +0000127 setDefaultInputDeviceInfo(*mTracker);
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000128 }
129 void TearDown() override {}
130
Siarhei Vishniakou363e7292021-07-09 03:22:42 +0000131 void triggerEventReporting(nsecs_t lastEventTime);
132
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000133 void assertReceivedTimeline(const InputEventTimeline& timeline);
134 /**
135 * Timelines can be received in any order (order is not guaranteed). So if we are expecting more
136 * than 1 timeline, use this function to check that the set of received timelines matches
137 * what we expected.
138 */
139 void assertReceivedTimelines(const std::vector<InputEventTimeline>& timelines);
140
141private:
142 void processTimeline(const InputEventTimeline& timeline) override {
143 mReceivedTimelines.push_back(timeline);
144 }
jioana24878b52024-09-10 10:13:27 +0000145 void pushLatencyStatistics() override {}
146 std::string dump(const char* prefix) const { return ""; };
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000147 std::deque<InputEventTimeline> mReceivedTimelines;
148};
149
Siarhei Vishniakou363e7292021-07-09 03:22:42 +0000150/**
151 * Send an event that would trigger the reporting of all of the events that are at least as old as
152 * the provided 'lastEventTime'.
153 */
154void LatencyTrackerTest::triggerEventReporting(nsecs_t lastEventTime) {
155 const nsecs_t triggerEventTime =
156 lastEventTime + std::chrono::nanoseconds(ANR_TIMEOUT).count() + 1;
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000157 mTracker->trackListener(MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL,
158 AINPUT_SOURCE_TOUCHSCREEN, /*inputEventId=*/1)
159 .eventTime(triggerEventTime)
160 .readTime(3)
161 .deviceId(DEVICE_ID)
162 .pointer(FIRST_TOUCH_POINTER)
163 .build());
Siarhei Vishniakou363e7292021-07-09 03:22:42 +0000164}
165
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000166void LatencyTrackerTest::assertReceivedTimeline(const InputEventTimeline& expectedTimeline) {
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000167 ASSERT_FALSE(mReceivedTimelines.empty());
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000168 const InputEventTimeline& received = mReceivedTimelines.front();
169 ASSERT_TRUE(timelinesAreEqual(received, expectedTimeline));
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000170 mReceivedTimelines.pop_front();
171}
172
173/**
174 * We are essentially comparing two multisets, but without constructing them.
175 * This comparison is inefficient, but it avoids having to construct a set, and also avoids the
176 * declaration of copy constructor for ConnectionTimeline.
177 * We ensure that collections A and B have the same size, that for every element in A, there is an
178 * equal element in B, and for every element in B there is an equal element in A.
179 */
180void LatencyTrackerTest::assertReceivedTimelines(const std::vector<InputEventTimeline>& timelines) {
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000181 ASSERT_EQ(timelines.size(), mReceivedTimelines.size());
182 for (const InputEventTimeline& expectedTimeline : timelines) {
183 bool found = false;
184 for (const InputEventTimeline& receivedTimeline : mReceivedTimelines) {
185 if (receivedTimeline == expectedTimeline) {
186 found = true;
187 break;
188 }
189 }
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000190 if (!found) {
191 for (const InputEventTimeline& receivedTimeline : mReceivedTimelines) {
192 LOG(ERROR) << "Received timeline with eventTime=" << receivedTimeline.eventTime;
193 }
194 }
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000195 ASSERT_TRUE(found) << "Could not find expected timeline with eventTime="
196 << expectedTimeline.eventTime;
197 }
198 for (const InputEventTimeline& receivedTimeline : mReceivedTimelines) {
199 bool found = false;
200 for (const InputEventTimeline& expectedTimeline : timelines) {
201 if (receivedTimeline == expectedTimeline) {
202 found = true;
203 break;
204 }
205 }
206 ASSERT_TRUE(found) << "Could not find received timeline with eventTime="
207 << receivedTimeline.eventTime;
208 }
209 mReceivedTimelines.clear();
210}
211
212/**
213 * Ensure that calling 'trackListener' in isolation only creates an inputflinger timeline, without
214 * any additional ConnectionTimeline's.
215 */
216TEST_F(LatencyTrackerTest, TrackListener_DoesNotTriggerReporting) {
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000217 mTracker->trackListener(MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL,
218 AINPUT_SOURCE_TOUCHSCREEN, /*inputEventId=*/1)
219 .eventTime(2)
220 .readTime(3)
221 .deviceId(DEVICE_ID)
222 .pointer(FIRST_TOUCH_POINTER)
223 .build());
Harry Cutts33476232023-01-30 19:57:29 +0000224 triggerEventReporting(/*eventTime=*/2);
jioana0bdbea12024-08-10 19:26:04 +0000225 assertReceivedTimeline(
jioana97cc8ac2024-09-09 15:01:43 +0000226 InputEventTimeline{/*eventTime=*/2,
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000227 /*readTime=*/3,
228 /*vendorId=*/0,
229 /*productID=*/0,
230 {InputDeviceUsageSource::TOUCHSCREEN},
jioana0bdbea12024-08-10 19:26:04 +0000231 /*inputEventActionType=*/InputEventActionType::UNKNOWN_INPUT_EVENT});
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000232}
233
234/**
235 * A single call to trackFinishedEvent should not cause a timeline to be reported.
236 */
237TEST_F(LatencyTrackerTest, TrackFinishedEvent_DoesNotTriggerReporting) {
Harry Cutts33476232023-01-30 19:57:29 +0000238 mTracker->trackFinishedEvent(/*inputEventId=*/1, connection1, /*deliveryTime=*/2,
239 /*consumeTime=*/3, /*finishTime=*/4);
240 triggerEventReporting(/*eventTime=*/4);
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000241 assertReceivedTimelines({});
242}
243
244/**
245 * A single call to trackGraphicsLatency should not cause a timeline to be reported.
246 */
247TEST_F(LatencyTrackerTest, TrackGraphicsLatency_DoesNotTriggerReporting) {
248 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
249 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
250 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
Harry Cutts33476232023-01-30 19:57:29 +0000251 mTracker->trackGraphicsLatency(/*inputEventId=*/1, connection2, graphicsTimeline);
252 triggerEventReporting(/*eventTime=*/3);
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000253 assertReceivedTimelines({});
254}
255
256TEST_F(LatencyTrackerTest, TrackAllParameters_ReportsFullTimeline) {
257 constexpr int32_t inputEventId = 1;
258 InputEventTimeline expected = getTestTimeline();
259
260 const auto& [connectionToken, expectedCT] = *expected.connectionTimelines.begin();
261
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000262 mTracker->trackListener(
263 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN, inputEventId)
264 .eventTime(expected.eventTime)
265 .readTime(expected.readTime)
266 .deviceId(DEVICE_ID)
267 .pointer(FIRST_TOUCH_POINTER)
268 .build());
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000269 mTracker->trackFinishedEvent(inputEventId, connectionToken, expectedCT.deliveryTime,
270 expectedCT.consumeTime, expectedCT.finishTime);
271 mTracker->trackGraphicsLatency(inputEventId, connectionToken, expectedCT.graphicsTimeline);
272
Siarhei Vishniakou363e7292021-07-09 03:22:42 +0000273 triggerEventReporting(expected.eventTime);
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000274 assertReceivedTimeline(expected);
275}
276
Siarhei Vishniakou363e7292021-07-09 03:22:42 +0000277/**
278 * Send 2 events with the same inputEventId, but different eventTime's. Ensure that no crash occurs,
279 * and that the tracker drops such events completely.
280 */
281TEST_F(LatencyTrackerTest, WhenDuplicateEventsAreReported_DoesNotCrash) {
282 constexpr nsecs_t inputEventId = 1;
283 constexpr nsecs_t readTime = 3; // does not matter for this test
Siarhei Vishniakou363e7292021-07-09 03:22:42 +0000284
285 // In the following 2 calls to trackListener, the inputEventId's are the same, but event times
286 // are different.
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000287 mTracker->trackListener(
288 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN, inputEventId)
289 .eventTime(1)
290 .readTime(readTime)
291 .deviceId(DEVICE_ID)
292 .pointer(FIRST_TOUCH_POINTER)
293 .build());
294 mTracker->trackListener(
295 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN, inputEventId)
296 .eventTime(2)
297 .readTime(readTime)
298 .deviceId(DEVICE_ID)
299 .pointer(FIRST_TOUCH_POINTER)
300 .build());
Siarhei Vishniakou363e7292021-07-09 03:22:42 +0000301
Harry Cutts33476232023-01-30 19:57:29 +0000302 triggerEventReporting(/*eventTime=*/2);
Siarhei Vishniakou363e7292021-07-09 03:22:42 +0000303 // Since we sent duplicate input events, the tracker should just delete all of them, because it
304 // does not have enough information to properly track them.
305 assertReceivedTimelines({});
306}
307
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000308TEST_F(LatencyTrackerTest, MultipleEvents_AreReportedConsistently) {
309 constexpr int32_t inputEventId1 = 1;
310 InputEventTimeline timeline1(
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000311 /*eventTime*/ 2,
Asmita Poddardd9a6cd2023-09-26 15:35:12 +0000312 /*readTime*/ 3,
313 /*vendorId=*/0,
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000314 /*productId=*/0, {InputDeviceUsageSource::TOUCHSCREEN},
jioana0bdbea12024-08-10 19:26:04 +0000315 /*inputEventType=*/InputEventActionType::UNKNOWN_INPUT_EVENT);
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000316 timeline1.connectionTimelines.emplace(connection1,
317 ConnectionTimeline(/*deliveryTime*/ 6, /*consumeTime*/ 7,
318 /*finishTime*/ 8));
319 ConnectionTimeline& connectionTimeline1 = timeline1.connectionTimelines.begin()->second;
320 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline1;
321 graphicsTimeline1[GraphicsTimeline::GPU_COMPLETED_TIME] = 9;
322 graphicsTimeline1[GraphicsTimeline::PRESENT_TIME] = 10;
323 connectionTimeline1.setGraphicsTimeline(std::move(graphicsTimeline1));
324
325 constexpr int32_t inputEventId2 = 10;
326 InputEventTimeline timeline2(
Harry Cutts33476232023-01-30 19:57:29 +0000327 /*eventTime=*/20,
Asmita Poddardd9a6cd2023-09-26 15:35:12 +0000328 /*readTime=*/30,
329 /*vendorId=*/0,
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000330 /*productId=*/0, {InputDeviceUsageSource::TOUCHSCREEN},
jioana0bdbea12024-08-10 19:26:04 +0000331 /*inputEventActionType=*/InputEventActionType::UNKNOWN_INPUT_EVENT);
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000332 timeline2.connectionTimelines.emplace(connection2,
Harry Cutts33476232023-01-30 19:57:29 +0000333 ConnectionTimeline(/*deliveryTime=*/60,
334 /*consumeTime=*/70,
335 /*finishTime=*/80));
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000336 ConnectionTimeline& connectionTimeline2 = timeline2.connectionTimelines.begin()->second;
337 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline2;
338 graphicsTimeline2[GraphicsTimeline::GPU_COMPLETED_TIME] = 90;
339 graphicsTimeline2[GraphicsTimeline::PRESENT_TIME] = 100;
340 connectionTimeline2.setGraphicsTimeline(std::move(graphicsTimeline2));
341
342 // Start processing first event
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000343 mTracker->trackListener(
344 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN, inputEventId1)
345 .eventTime(timeline1.eventTime)
346 .readTime(timeline1.readTime)
347 .deviceId(DEVICE_ID)
348 .pointer(FIRST_TOUCH_POINTER)
349 .build());
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000350 // Start processing second event
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000351 mTracker->trackListener(
352 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN, inputEventId2)
353 .eventTime(timeline2.eventTime)
354 .readTime(timeline2.readTime)
355 .deviceId(DEVICE_ID)
356 .pointer(FIRST_TOUCH_POINTER)
357 .build());
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000358 mTracker->trackFinishedEvent(inputEventId1, connection1, connectionTimeline1.deliveryTime,
359 connectionTimeline1.consumeTime, connectionTimeline1.finishTime);
360
361 mTracker->trackFinishedEvent(inputEventId2, connection2, connectionTimeline2.deliveryTime,
362 connectionTimeline2.consumeTime, connectionTimeline2.finishTime);
363 mTracker->trackGraphicsLatency(inputEventId1, connection1,
364 connectionTimeline1.graphicsTimeline);
365 mTracker->trackGraphicsLatency(inputEventId2, connection2,
366 connectionTimeline2.graphicsTimeline);
367 // Now both events should be completed
Siarhei Vishniakou363e7292021-07-09 03:22:42 +0000368 triggerEventReporting(timeline2.eventTime);
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000369 assertReceivedTimelines({timeline1, timeline2});
370}
371
372/**
373 * Check that LatencyTracker consistently tracks events even if there are many incomplete events.
374 */
375TEST_F(LatencyTrackerTest, IncompleteEvents_AreHandledConsistently) {
376 InputEventTimeline timeline = getTestTimeline();
377 std::vector<InputEventTimeline> expectedTimelines;
378 const ConnectionTimeline& expectedCT = timeline.connectionTimelines.begin()->second;
379 const sp<IBinder>& token = timeline.connectionTimelines.begin()->first;
380
381 for (size_t i = 1; i <= 100; i++) {
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000382 mTracker->trackListener(MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL,
383 AINPUT_SOURCE_TOUCHSCREEN, /*inputEventId=*/i)
384 .eventTime(timeline.eventTime)
385 .readTime(timeline.readTime)
386 .deviceId(DEVICE_ID)
387 .pointer(FIRST_TOUCH_POINTER)
388 .build());
jioana97cc8ac2024-09-09 15:01:43 +0000389 expectedTimelines.push_back(InputEventTimeline{timeline.eventTime, timeline.readTime,
390 timeline.vendorId, timeline.productId,
391 timeline.sources,
jioana0bdbea12024-08-10 19:26:04 +0000392 timeline.inputEventActionType});
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000393 }
394 // Now, complete the first event that was sent.
Harry Cutts33476232023-01-30 19:57:29 +0000395 mTracker->trackFinishedEvent(/*inputEventId=*/1, token, expectedCT.deliveryTime,
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000396 expectedCT.consumeTime, expectedCT.finishTime);
Harry Cutts33476232023-01-30 19:57:29 +0000397 mTracker->trackGraphicsLatency(/*inputEventId=*/1, token, expectedCT.graphicsTimeline);
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000398
399 expectedTimelines[0].connectionTimelines.emplace(token, std::move(expectedCT));
Siarhei Vishniakou363e7292021-07-09 03:22:42 +0000400 triggerEventReporting(timeline.eventTime);
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000401 assertReceivedTimelines(expectedTimelines);
402}
403
404/**
405 * For simplicity of the implementation, LatencyTracker only starts tracking an event when
406 * 'trackListener' is invoked.
407 * Both 'trackFinishedEvent' and 'trackGraphicsLatency' should not start a new event.
408 * If they are received before 'trackListener' (which should not be possible), they are ignored.
409 */
410TEST_F(LatencyTrackerTest, EventsAreTracked_WhenTrackListenerIsCalledFirst) {
411 constexpr int32_t inputEventId = 1;
412 InputEventTimeline expected = getTestTimeline();
413 const ConnectionTimeline& expectedCT = expected.connectionTimelines.begin()->second;
414 mTracker->trackFinishedEvent(inputEventId, connection1, expectedCT.deliveryTime,
415 expectedCT.consumeTime, expectedCT.finishTime);
416 mTracker->trackGraphicsLatency(inputEventId, connection1, expectedCT.graphicsTimeline);
417
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000418 mTracker->trackListener(
419 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN, inputEventId)
420 .eventTime(expected.eventTime)
421 .readTime(expected.readTime)
422 .deviceId(DEVICE_ID)
423 .pointer(FIRST_TOUCH_POINTER)
424 .build());
Siarhei Vishniakou363e7292021-07-09 03:22:42 +0000425 triggerEventReporting(expected.eventTime);
jioana97cc8ac2024-09-09 15:01:43 +0000426 assertReceivedTimeline(InputEventTimeline{expected.eventTime, expected.readTime,
427 expected.vendorId, expected.productId,
428 expected.sources, expected.inputEventActionType});
Asmita Poddardd9a6cd2023-09-26 15:35:12 +0000429}
430
431/**
432 * Check that LatencyTracker has the received timeline that contains the correctly
433 * resolved product ID, vendor ID and source for a particular device ID from
434 * among a list of devices.
435 */
436TEST_F(LatencyTrackerTest, TrackListenerCheck_DeviceInfoFieldsInputEventTimeline) {
437 constexpr int32_t inputEventId = 1;
438 InputEventTimeline timeline(
jioana97cc8ac2024-09-09 15:01:43 +0000439 /*eventTime*/ 2, /*readTime*/ 3,
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000440 /*vendorId=*/50, /*productId=*/60, {InputDeviceUsageSource::STYLUS_DIRECT},
jioana0bdbea12024-08-10 19:26:04 +0000441 /*inputEventActionType=*/InputEventActionType::UNKNOWN_INPUT_EVENT);
Asmita Poddardd9a6cd2023-09-26 15:35:12 +0000442 InputDeviceInfo deviceInfo1 = generateTestDeviceInfo(
443 /*vendorId=*/5, /*productId=*/6, /*deviceId=*/DEVICE_ID + 1);
444 InputDeviceInfo deviceInfo2 = generateTestDeviceInfo(
445 /*vendorId=*/50, /*productId=*/60, /*deviceId=*/DEVICE_ID);
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000446 deviceInfo2.addSource(AINPUT_SOURCE_TOUCHSCREEN);
447 deviceInfo2.addSource(AINPUT_SOURCE_STYLUS);
Asmita Poddardd9a6cd2023-09-26 15:35:12 +0000448
449 mTracker->setInputDevices({deviceInfo1, deviceInfo2});
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000450 mTracker->trackListener(
451 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL,
452 AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, inputEventId)
453
454 .eventTime(timeline.eventTime)
455 .readTime(timeline.readTime)
456 .deviceId(DEVICE_ID)
457 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(100).y(200))
458 .build());
Asmita Poddardd9a6cd2023-09-26 15:35:12 +0000459 triggerEventReporting(timeline.eventTime);
460 assertReceivedTimeline(timeline);
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000461}
462
jioana0bdbea12024-08-10 19:26:04 +0000463/**
464 * Check that InputEventActionType is correctly assigned to InputEventTimeline in trackListener.
465 */
466TEST_F(LatencyTrackerTest, TrackListenerCheck_InputEventActionTypeFieldInputEventTimeline) {
467 constexpr int32_t inputEventId = 1;
468 // Create timelines for different event types (Motion, Key)
469 InputEventTimeline motionDownTimeline(
jioana97cc8ac2024-09-09 15:01:43 +0000470 /*eventTime*/ 2, /*readTime*/ 3,
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000471 /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::TOUCHSCREEN},
472 InputEventActionType::MOTION_ACTION_DOWN);
jioana0bdbea12024-08-10 19:26:04 +0000473
474 InputEventTimeline motionMoveTimeline(
jioana97cc8ac2024-09-09 15:01:43 +0000475 /*eventTime*/ 4, /*readTime*/ 5,
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000476 /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::TOUCHSCREEN},
477 InputEventActionType::MOTION_ACTION_MOVE);
jioana0bdbea12024-08-10 19:26:04 +0000478
479 InputEventTimeline motionUpTimeline(
jioana97cc8ac2024-09-09 15:01:43 +0000480 /*eventTime*/ 6, /*readTime*/ 7,
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000481 /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::TOUCHSCREEN},
482 InputEventActionType::MOTION_ACTION_UP);
jioana0bdbea12024-08-10 19:26:04 +0000483
484 InputEventTimeline keyDownTimeline(
jioana97cc8ac2024-09-09 15:01:43 +0000485 /*eventTime*/ 8, /*readTime*/ 9,
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000486 /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::BUTTONS},
487 InputEventActionType::KEY);
jioana0bdbea12024-08-10 19:26:04 +0000488
489 InputEventTimeline keyUpTimeline(
jioana97cc8ac2024-09-09 15:01:43 +0000490 /*eventTime*/ 10, /*readTime*/ 11,
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000491 /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::BUTTONS},
492 InputEventActionType::KEY);
jioana0bdbea12024-08-10 19:26:04 +0000493
494 InputEventTimeline unknownTimeline(
jioana97cc8ac2024-09-09 15:01:43 +0000495 /*eventTime*/ 12, /*readTime*/ 13,
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000496 /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::TOUCHSCREEN},
497 InputEventActionType::UNKNOWN_INPUT_EVENT);
jioana0bdbea12024-08-10 19:26:04 +0000498
Siarhei Vishniakou93ee5402024-10-09 00:07:23 +0000499 mTracker->trackListener(
500 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, inputEventId)
501 .eventTime(motionDownTimeline.eventTime)
502 .readTime(motionDownTimeline.readTime)
503 .deviceId(DEVICE_ID)
504 .pointer(FIRST_TOUCH_POINTER)
505 .build());
506 mTracker->trackListener(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
507 inputEventId + 1)
508 .eventTime(motionMoveTimeline.eventTime)
509 .readTime(motionMoveTimeline.readTime)
510 .deviceId(DEVICE_ID)
511 .pointer(FIRST_TOUCH_POINTER)
512 .build());
513 mTracker->trackListener(
514 MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, inputEventId + 2)
515 .eventTime(motionUpTimeline.eventTime)
516 .readTime(motionUpTimeline.readTime)
517 .deviceId(DEVICE_ID)
518 .pointer(FIRST_TOUCH_POINTER)
519 .build());
520 mTracker->trackListener(
521 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD, inputEventId + 3)
522 .eventTime(keyDownTimeline.eventTime)
523 .readTime(keyDownTimeline.readTime)
524 .deviceId(DEVICE_ID)
525 .build());
526 mTracker->trackListener(
527 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD, inputEventId + 4)
528 .eventTime(keyUpTimeline.eventTime)
529 .readTime(keyUpTimeline.readTime)
530 .deviceId(DEVICE_ID)
531 .build());
532 mTracker->trackListener(MotionArgsBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN,
533 AINPUT_SOURCE_TOUCHSCREEN, inputEventId + 5)
534 .eventTime(unknownTimeline.eventTime)
535 .readTime(unknownTimeline.readTime)
536 .deviceId(DEVICE_ID)
537 .pointer(FIRST_TOUCH_POINTER)
538 .build());
jioana0bdbea12024-08-10 19:26:04 +0000539
540 triggerEventReporting(unknownTimeline.eventTime);
541
542 std::vector<InputEventTimeline> expectedTimelines = {motionDownTimeline, motionMoveTimeline,
543 motionUpTimeline, keyDownTimeline,
544 keyUpTimeline, unknownTimeline};
545 assertReceivedTimelines(expectedTimelines);
546}
547
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000548} // namespace android::inputdispatcher