1 /**
2 * Copyright 2024 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 <input/InputConsumerNoResampling.h>
18
19 #include <gtest/gtest.h>
20
21 #include <chrono>
22 #include <memory>
23 #include <optional>
24
25 #include <TestEventMatchers.h>
26 #include <TestInputChannel.h>
27 #include <android-base/logging.h>
28 #include <gmock/gmock.h>
29 #include <gtest/gtest.h>
30 #include <input/BlockingQueue.h>
31 #include <input/Input.h>
32 #include <input/InputEventBuilders.h>
33 #include <input/Resampler.h>
34 #include <utils/Looper.h>
35 #include <utils/StrongPointer.h>
36
37 namespace android {
38
39 namespace {
40
41 using std::chrono::nanoseconds;
42
43 using ::testing::AllOf;
44 using ::testing::Matcher;
45
46 constexpr auto ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
47 constexpr auto ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
48
49 struct Pointer {
50 int32_t id{0};
51 ToolType toolType{ToolType::FINGER};
52 float x{0.0f};
53 float y{0.0f};
54 bool isResampled{false};
55
asPointerBuilderandroid::__anon6421ff810111::Pointer56 PointerBuilder asPointerBuilder() const {
57 return PointerBuilder{id, toolType}.x(x).y(y).isResampled(isResampled);
58 }
59 };
60 } // namespace
61
62 class InputConsumerTest : public testing::Test, public InputConsumerCallbacks {
63 protected:
InputConsumerTest()64 InputConsumerTest()
65 : mClientTestChannel{std::make_shared<TestInputChannel>("TestChannel")},
66 mLooper{sp<Looper>::make(/*allowNonCallbacks=*/false)} {
67 Looper::setForThread(mLooper);
68 mConsumer = std::make_unique<
69 InputConsumerNoResampling>(mClientTestChannel, mLooper, *this,
__anon6421ff810202() 70 []() { return std::make_unique<LegacyResampler>(); });
71 }
72
invokeLooperCallback() const73 bool invokeLooperCallback() const {
74 sp<LooperCallback> callback;
75 const bool found =
76 mLooper->getFdStateDebug(mClientTestChannel->getFd(), /*ident=*/nullptr,
77 /*events=*/nullptr, &callback, /*data=*/nullptr);
78 if (!found) {
79 return false;
80 }
81 if (callback == nullptr) {
82 LOG(FATAL) << "Looper has the fd of interest, but the callback is null!";
83 return false;
84 }
85 callback->handleEvent(mClientTestChannel->getFd(), ALOOPER_EVENT_INPUT, /*data=*/nullptr);
86 return true;
87 }
88
assertOnBatchedInputEventPendingWasCalled()89 void assertOnBatchedInputEventPendingWasCalled() {
90 ASSERT_GT(mOnBatchedInputEventPendingInvocationCount, 0UL)
91 << "onBatchedInputEventPending has not been called.";
92 --mOnBatchedInputEventPendingInvocationCount;
93 }
94
assertReceivedMotionEvent(const Matcher<MotionEvent> & matcher)95 std::unique_ptr<MotionEvent> assertReceivedMotionEvent(const Matcher<MotionEvent>& matcher) {
96 if (mMotionEvents.empty()) {
97 ADD_FAILURE() << "No motion events received";
98 return nullptr;
99 }
100 std::unique_ptr<MotionEvent> motionEvent = std::move(mMotionEvents.front());
101 mMotionEvents.pop();
102 if (motionEvent == nullptr) {
103 ADD_FAILURE() << "The consumed motion event should never be null";
104 return nullptr;
105 }
106 EXPECT_THAT(*motionEvent, matcher);
107 return motionEvent;
108 }
109
110 InputMessage nextPointerMessage(std::chrono::nanoseconds eventTime, DeviceId deviceId,
111 int32_t action, const Pointer& pointer);
112
113 std::shared_ptr<TestInputChannel> mClientTestChannel;
114 sp<Looper> mLooper;
115 std::unique_ptr<InputConsumerNoResampling> mConsumer;
116
117 std::queue<std::unique_ptr<KeyEvent>> mKeyEvents;
118 std::queue<std::unique_ptr<MotionEvent>> mMotionEvents;
119 std::queue<std::unique_ptr<FocusEvent>> mFocusEvents;
120 std::queue<std::unique_ptr<CaptureEvent>> mCaptureEvents;
121 std::queue<std::unique_ptr<DragEvent>> mDragEvents;
122 std::queue<std::unique_ptr<TouchModeEvent>> mTouchModeEvents;
123
124 // Whether or not to automatically call "finish" whenever a motion event is received.
125 bool mShouldFinishMotions{true};
126
127 private:
128 uint32_t mLastSeq{0};
129 size_t mOnBatchedInputEventPendingInvocationCount{0};
130
131 // InputConsumerCallbacks interface
onKeyEvent(std::unique_ptr<KeyEvent> event,uint32_t seq)132 void onKeyEvent(std::unique_ptr<KeyEvent> event, uint32_t seq) override {
133 mKeyEvents.push(std::move(event));
134 mConsumer->finishInputEvent(seq, /*handled=*/true);
135 }
onMotionEvent(std::unique_ptr<MotionEvent> event,uint32_t seq)136 void onMotionEvent(std::unique_ptr<MotionEvent> event, uint32_t seq) override {
137 mMotionEvents.push(std::move(event));
138 if (mShouldFinishMotions) {
139 mConsumer->finishInputEvent(seq, /*handled=*/true);
140 }
141 }
onBatchedInputEventPending(int32_t pendingBatchSource)142 void onBatchedInputEventPending(int32_t pendingBatchSource) override {
143 if (!mConsumer->probablyHasInput()) {
144 ADD_FAILURE() << "should deterministically have input because there is a batch";
145 }
146 ++mOnBatchedInputEventPendingInvocationCount;
147 };
onFocusEvent(std::unique_ptr<FocusEvent> event,uint32_t seq)148 void onFocusEvent(std::unique_ptr<FocusEvent> event, uint32_t seq) override {
149 mFocusEvents.push(std::move(event));
150 mConsumer->finishInputEvent(seq, /*handled=*/true);
151 };
onCaptureEvent(std::unique_ptr<CaptureEvent> event,uint32_t seq)152 void onCaptureEvent(std::unique_ptr<CaptureEvent> event, uint32_t seq) override {
153 mCaptureEvents.push(std::move(event));
154 mConsumer->finishInputEvent(seq, /*handled=*/true);
155 };
onDragEvent(std::unique_ptr<DragEvent> event,uint32_t seq)156 void onDragEvent(std::unique_ptr<DragEvent> event, uint32_t seq) override {
157 mDragEvents.push(std::move(event));
158 mConsumer->finishInputEvent(seq, /*handled=*/true);
159 }
onTouchModeEvent(std::unique_ptr<TouchModeEvent> event,uint32_t seq)160 void onTouchModeEvent(std::unique_ptr<TouchModeEvent> event, uint32_t seq) override {
161 mTouchModeEvents.push(std::move(event));
162 mConsumer->finishInputEvent(seq, /*handled=*/true);
163 };
164 };
165
nextPointerMessage(std::chrono::nanoseconds eventTime,DeviceId deviceId,int32_t action,const Pointer & pointer)166 InputMessage InputConsumerTest::nextPointerMessage(std::chrono::nanoseconds eventTime,
167 DeviceId deviceId, int32_t action,
168 const Pointer& pointer) {
169 ++mLastSeq;
170 return InputMessageBuilder{InputMessage::Type::MOTION, mLastSeq}
171 .eventTime(eventTime.count())
172 .deviceId(deviceId)
173 .source(AINPUT_SOURCE_TOUCHSCREEN)
174 .action(action)
175 .pointer(pointer.asPointerBuilder())
176 .build();
177 }
178
TEST_F(InputConsumerTest,MessageStreamBatchedInMotionEvent)179 TEST_F(InputConsumerTest, MessageStreamBatchedInMotionEvent) {
180 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/0}
181 .eventTime(nanoseconds{0ms}.count())
182 .action(ACTION_DOWN)
183 .build());
184 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/1}
185 .eventTime(nanoseconds{5ms}.count())
186 .action(ACTION_MOVE)
187 .build());
188 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/2}
189 .eventTime(nanoseconds{10ms}.count())
190 .action(ACTION_MOVE)
191 .build());
192
193 mClientTestChannel->assertNoSentMessages();
194
195 invokeLooperCallback();
196
197 assertOnBatchedInputEventPendingWasCalled();
198
199 mConsumer->consumeBatchedInputEvents(/*frameTime=*/std::nullopt);
200
201 assertReceivedMotionEvent(WithMotionAction(ACTION_DOWN));
202
203 std::unique_ptr<MotionEvent> moveMotionEvent =
204 assertReceivedMotionEvent(WithMotionAction(ACTION_MOVE));
205 ASSERT_NE(moveMotionEvent, nullptr);
206 EXPECT_EQ(moveMotionEvent->getHistorySize() + 1, 2UL);
207
208 mClientTestChannel->assertFinishMessage(/*seq=*/0, /*handled=*/true);
209 mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true);
210 mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true);
211 }
212
TEST_F(InputConsumerTest,LastBatchedSampleIsLessThanResampleTime)213 TEST_F(InputConsumerTest, LastBatchedSampleIsLessThanResampleTime) {
214 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/0}
215 .eventTime(nanoseconds{0ms}.count())
216 .action(ACTION_DOWN)
217 .build());
218 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/1}
219 .eventTime(nanoseconds{5ms}.count())
220 .action(ACTION_MOVE)
221 .build());
222 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/2}
223 .eventTime(nanoseconds{10ms}.count())
224 .action(ACTION_MOVE)
225 .build());
226 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/3}
227 .eventTime(nanoseconds{15ms}.count())
228 .action(ACTION_MOVE)
229 .build());
230
231 mClientTestChannel->assertNoSentMessages();
232
233 invokeLooperCallback();
234
235 assertOnBatchedInputEventPendingWasCalled();
236
237 mConsumer->consumeBatchedInputEvents(16'000'000 /*ns*/);
238
239 assertReceivedMotionEvent(WithMotionAction(ACTION_DOWN));
240
241 std::unique_ptr<MotionEvent> moveMotionEvent =
242 assertReceivedMotionEvent(WithMotionAction(ACTION_MOVE));
243 ASSERT_NE(moveMotionEvent, nullptr);
244 const size_t numSamples = moveMotionEvent->getHistorySize() + 1;
245 EXPECT_LT(moveMotionEvent->getHistoricalEventTime(numSamples - 2),
246 moveMotionEvent->getEventTime());
247
248 mClientTestChannel->assertFinishMessage(/*seq=*/0, /*handled=*/true);
249 mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true);
250 mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true);
251 // The event with seq=3 remains unconsumed, and therefore finish will not be called for it until
252 // after the consumer is destroyed.
253 mConsumer.reset();
254 mClientTestChannel->assertFinishMessage(/*seq=*/3, /*handled=*/false);
255 mClientTestChannel->assertNoSentMessages();
256 }
257
258 /**
259 * During normal operation, the user of InputConsumer (callbacks) is expected to call "finish"
260 * for each input event received in InputConsumerCallbacks.
261 * If the InputConsumer is destroyed, the events that were already sent to the callbacks will not
262 * be finished automatically.
263 */
TEST_F(InputConsumerTest,UnhandledEventsNotFinishedInDestructor)264 TEST_F(InputConsumerTest, UnhandledEventsNotFinishedInDestructor) {
265 mClientTestChannel->enqueueMessage(
266 InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/0}.action(ACTION_DOWN).build());
267 mClientTestChannel->enqueueMessage(
268 InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/1}.action(ACTION_MOVE).build());
269 mShouldFinishMotions = false;
270 invokeLooperCallback();
271 assertOnBatchedInputEventPendingWasCalled();
272 assertReceivedMotionEvent(WithMotionAction(ACTION_DOWN));
273 mClientTestChannel->assertNoSentMessages();
274 // The "finishInputEvent" was not called by the InputConsumerCallbacks.
275 // Now, destroy the consumer and check that the "finish" was not called automatically for the
276 // DOWN event, but was called for the undelivered MOVE event.
277 mConsumer.reset();
278 mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/false);
279 mClientTestChannel->assertNoSentMessages();
280 }
281
282 /**
283 * Check what happens when looper invokes callback after consumer has been destroyed.
284 * This reproduces a crash where the LooperEventCallback was added back to the Looper during
285 * destructor, thus allowing the looper callback to be invoked onto a null consumer object.
286 */
TEST_F(InputConsumerTest,LooperCallbackInvokedAfterConsumerDestroyed)287 TEST_F(InputConsumerTest, LooperCallbackInvokedAfterConsumerDestroyed) {
288 mClientTestChannel->enqueueMessage(
289 InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/0}.action(ACTION_DOWN).build());
290 mClientTestChannel->enqueueMessage(
291 InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/1}.action(ACTION_MOVE).build());
292 ASSERT_TRUE(invokeLooperCallback());
293 assertOnBatchedInputEventPendingWasCalled();
294 assertReceivedMotionEvent(WithMotionAction(ACTION_DOWN));
295 mClientTestChannel->assertFinishMessage(/*seq=*/0, /*handled=*/true);
296
297 // Now, destroy the consumer and invoke the looper callback again after it's been destroyed.
298 mConsumer.reset();
299 mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/false);
300 ASSERT_FALSE(invokeLooperCallback());
301 }
302
303 /**
304 * Send an event to the InputConsumer, but do not invoke "consumeBatchedInputEvents", thus leaving
305 * the input event unconsumed by the callbacks. Ensure that no crash occurs when the consumer is
306 * destroyed.
307 * This test is similar to the one above, but here we are calling "finish"
308 * automatically for any event received in the callbacks.
309 */
TEST_F(InputConsumerTest,UnconsumedEventDoesNotCauseACrash)310 TEST_F(InputConsumerTest, UnconsumedEventDoesNotCauseACrash) {
311 mClientTestChannel->enqueueMessage(
312 InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/0}.action(ACTION_DOWN).build());
313 invokeLooperCallback();
314 assertReceivedMotionEvent(WithMotionAction(ACTION_DOWN));
315 mClientTestChannel->assertFinishMessage(/*seq=*/0, /*handled=*/true);
316 mClientTestChannel->enqueueMessage(
317 InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/1}.action(ACTION_MOVE).build());
318 invokeLooperCallback();
319 mConsumer.reset();
320 mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/false);
321 }
322
TEST_F(InputConsumerTest,BatchedEventsMultiDeviceConsumption)323 TEST_F(InputConsumerTest, BatchedEventsMultiDeviceConsumption) {
324 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/0}
325 .deviceId(0)
326 .action(ACTION_DOWN)
327 .build());
328
329 invokeLooperCallback();
330 assertReceivedMotionEvent(AllOf(WithDeviceId(0), WithMotionAction(ACTION_DOWN)));
331
332 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/1}
333 .deviceId(0)
334 .action(ACTION_MOVE)
335 .build());
336 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/2}
337 .deviceId(0)
338 .action(ACTION_MOVE)
339 .build());
340 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/3}
341 .deviceId(0)
342 .action(ACTION_MOVE)
343 .build());
344
345 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/4}
346 .deviceId(1)
347 .action(ACTION_DOWN)
348 .build());
349
350 invokeLooperCallback();
351 assertReceivedMotionEvent(AllOf(WithDeviceId(1), WithMotionAction(ACTION_DOWN)));
352
353 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/5}
354 .deviceId(0)
355 .action(AMOTION_EVENT_ACTION_UP)
356 .build());
357
358 invokeLooperCallback();
359 assertReceivedMotionEvent(AllOf(WithDeviceId(0), WithMotionAction(ACTION_MOVE)));
360
361 mClientTestChannel->assertFinishMessage(/*seq=*/0, /*handled=*/true);
362 mClientTestChannel->assertFinishMessage(/*seq=*/4, /*handled=*/true);
363 mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true);
364 mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true);
365 mClientTestChannel->assertFinishMessage(/*seq=*/3, /*handled=*/true);
366 }
367
368 /**
369 * The test supposes a 60Hz Vsync rate and a 200Hz input rate. The InputMessages are intertwined as
370 * in a real use cases. The test's two devices should be resampled independently. Moreover, the
371 * InputMessage stream layout for the test is:
372 *
373 * DOWN(0, 0ms)
374 * MOVE(0, 5ms)
375 * MOVE(0, 10ms)
376 * DOWN(1, 15ms)
377 *
378 * CONSUME(16ms)
379 *
380 * MOVE(1, 20ms)
381 * MOVE(1, 25ms)
382 * MOVE(0, 30ms)
383 *
384 * CONSUME(32ms)
385 *
386 * MOVE(0, 35ms)
387 * UP(1, 40ms)
388 * UP(0, 45ms)
389 *
390 * CONSUME(48ms)
391 *
392 * The first field is device ID, and the second field is event time.
393 */
TEST_F(InputConsumerTest,MultiDeviceResampling)394 TEST_F(InputConsumerTest, MultiDeviceResampling) {
395 mClientTestChannel->enqueueMessage(
396 nextPointerMessage(0ms, /*deviceId=*/0, ACTION_DOWN, Pointer{.x = 0, .y = 0}));
397
398 mClientTestChannel->assertNoSentMessages();
399
400 invokeLooperCallback();
401 assertReceivedMotionEvent(
402 AllOf(WithDeviceId(0), WithMotionAction(ACTION_DOWN), WithSampleCount(1)));
403
404 mClientTestChannel->enqueueMessage(
405 nextPointerMessage(5ms, /*deviceId=*/0, ACTION_MOVE, Pointer{.x = 1.0f, .y = 2.0f}));
406 mClientTestChannel->enqueueMessage(
407 nextPointerMessage(10ms, /*deviceId=*/0, ACTION_MOVE, Pointer{.x = 2.0f, .y = 4.0f}));
408 mClientTestChannel->enqueueMessage(
409 nextPointerMessage(15ms, /*deviceId=*/1, ACTION_DOWN, Pointer{.x = 10.0f, .y = 10.0f}));
410
411 invokeLooperCallback();
412 mConsumer->consumeBatchedInputEvents(16'000'000 /*ns*/);
413
414 assertReceivedMotionEvent(
415 AllOf(WithDeviceId(1), WithMotionAction(ACTION_DOWN), WithSampleCount(1)));
416 assertReceivedMotionEvent(
417 AllOf(WithDeviceId(0), WithMotionAction(ACTION_MOVE), WithSampleCount(3),
418 WithSample(/*sampleIndex=*/2,
419 Sample{11ms,
420 {PointerArgs{.x = 2.2f, .y = 4.4f, .isResampled = true}}})));
421
422 mClientTestChannel->enqueueMessage(
423 nextPointerMessage(20ms, /*deviceId=*/1, ACTION_MOVE, Pointer{.x = 11.0f, .y = 12.0f}));
424 mClientTestChannel->enqueueMessage(
425 nextPointerMessage(25ms, /*deviceId=*/1, ACTION_MOVE, Pointer{.x = 12.0f, .y = 14.0f}));
426 mClientTestChannel->enqueueMessage(
427 nextPointerMessage(30ms, /*deviceId=*/0, ACTION_MOVE, Pointer{.x = 5.0f, .y = 6.0f}));
428
429 invokeLooperCallback();
430 assertOnBatchedInputEventPendingWasCalled();
431 mConsumer->consumeBatchedInputEvents(32'000'000 /*ns*/);
432
433 assertReceivedMotionEvent(
434 AllOf(WithDeviceId(1), WithMotionAction(ACTION_MOVE), WithSampleCount(3),
435 WithSample(/*sampleIndex=*/2,
436 Sample{27ms,
437 {PointerArgs{.x = 12.4f, .y = 14.8f, .isResampled = true}}})));
438
439 mClientTestChannel->enqueueMessage(
440 nextPointerMessage(35ms, /*deviceId=*/0, ACTION_MOVE, Pointer{.x = 8.0f, .y = 9.0f}));
441 mClientTestChannel->enqueueMessage(nextPointerMessage(40ms, /*deviceId=*/1,
442 AMOTION_EVENT_ACTION_UP,
443 Pointer{.x = 12.0f, .y = 14.0f}));
444 mClientTestChannel->enqueueMessage(nextPointerMessage(45ms, /*deviceId=*/0,
445 AMOTION_EVENT_ACTION_UP,
446 Pointer{.x = 8.0f, .y = 9.0f}));
447
448 invokeLooperCallback();
449 mConsumer->consumeBatchedInputEvents(48'000'000 /*ns*/);
450
451 assertReceivedMotionEvent(
452 AllOf(WithDeviceId(1), WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSampleCount(1)));
453
454 assertReceivedMotionEvent(
455 AllOf(WithDeviceId(0), WithMotionAction(ACTION_MOVE), WithSampleCount(3),
456 WithSample(/*sampleIndex=*/2,
457 Sample{37'500'000ns,
458 {PointerArgs{.x = 9.5f, .y = 10.5f, .isResampled = true}}})));
459
460 assertReceivedMotionEvent(
461 AllOf(WithDeviceId(0), WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSampleCount(1)));
462
463 // The sequence order is based on the expected consumption. Each sequence number corresponds to
464 // one of the previously enqueued messages.
465 mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true);
466 mClientTestChannel->assertFinishMessage(/*seq=*/4, /*handled=*/true);
467 mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true);
468 mClientTestChannel->assertFinishMessage(/*seq=*/3, /*handled=*/true);
469 mClientTestChannel->assertFinishMessage(/*seq=*/5, /*handled=*/true);
470 mClientTestChannel->assertFinishMessage(/*seq=*/6, /*handled=*/true);
471 mClientTestChannel->assertFinishMessage(/*seq=*/9, /*handled=*/true);
472 mClientTestChannel->assertFinishMessage(/*seq=*/7, /*handled=*/true);
473 mClientTestChannel->assertFinishMessage(/*seq=*/8, /*handled=*/true);
474 mClientTestChannel->assertFinishMessage(/*seq=*/10, /*handled=*/true);
475 }
476
477 } // namespace android
478