blob: fe4d6d9a8f9f06e9ec053f6981631bab95cd4a0d [file] [log] [blame]
Prabir Pradhan9a9897d2024-03-21 21:52:57 +00001/*
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 "../InputCommonConverter.h"
18#include "../dispatcher/InputDispatcher.h"
19#include "../dispatcher/trace/InputTracingPerfettoBackend.h"
20#include "../dispatcher/trace/ThreadedBackend.h"
21#include "FakeApplicationHandle.h"
22#include "FakeInputDispatcherPolicy.h"
23#include "FakeWindows.h"
24#include "InputTraceSession.h"
25#include "TestEventMatchers.h"
26
27#include <NotifyArgsBuilders.h>
28#include <android-base/logging.h>
29#include <gtest/gtest.h>
30#include <input/Input.h>
31#include <perfetto/trace/android/android_input_event.pbzero.h>
32#include <perfetto/trace/trace.pbzero.h>
33#include <private/android_filesystem_config.h>
34#include <map>
35#include <vector>
36
37namespace android::inputdispatcher::trace {
38
39using perfetto::protos::pbzero::AndroidInputEventConfig;
40
41namespace {
42
43constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
44
45// Ensure common actions are interchangeable between keys and motions for convenience.
46static_assert(static_cast<int32_t>(AMOTION_EVENT_ACTION_DOWN) ==
47 static_cast<int32_t>(AKEY_EVENT_ACTION_DOWN));
48static_assert(static_cast<int32_t>(AMOTION_EVENT_ACTION_UP) ==
49 static_cast<int32_t>(AKEY_EVENT_ACTION_UP));
50constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
51constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
52constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
53constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
54
55constexpr gui::Pid PID{1};
56
57constexpr gui::Uid ALLOWED_UID_1{10012};
58constexpr gui::Uid ALLOWED_UID_2{10013};
59constexpr gui::Uid DISALLOWED_UID_1{1};
60constexpr gui::Uid DISALLOWED_UID_2{99};
61constexpr gui::Uid UNLISTED_UID{12345};
62
63const std::string ALLOWED_PKG_1{"allowed.pkg.1"};
64const std::string ALLOWED_PKG_2{"allowed.pkg.2"};
65const std::string DISALLOWED_PKG_1{"disallowed.pkg.1"};
66const std::string DISALLOWED_PKG_2{"disallowed.pkg.2"};
67
68const std::shared_ptr<FakeApplicationHandle> APP = std::make_shared<FakeApplicationHandle>();
69
70} // namespace
71
72// --- InputTracingTest ---
73
74class InputTracingTest : public testing::Test {
75protected:
76 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
77 std::unique_ptr<InputDispatcher> mDispatcher;
78
79 void SetUp() override {
80 impl::PerfettoBackend::sUseInProcessBackendForTest = true;
81
82 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
83 mFakePolicy->addPackageUidMapping(ALLOWED_PKG_1, ALLOWED_UID_1);
84 mFakePolicy->addPackageUidMapping(ALLOWED_PKG_2, ALLOWED_UID_2);
85 mFakePolicy->addPackageUidMapping(DISALLOWED_PKG_1, DISALLOWED_UID_1);
86 mFakePolicy->addPackageUidMapping(DISALLOWED_PKG_2, DISALLOWED_UID_2);
87
88 auto tracingBackend = std::make_unique<impl::ThreadedBackend<impl::PerfettoBackend>>(
89 impl::PerfettoBackend([this](const auto& pkg) {
90 return static_cast<InputDispatcherPolicyInterface&>(*mFakePolicy)
91 .getPackageUid(pkg);
92 }));
93 mRequestTracerIdle = tracingBackend->getIdleWaiterForTesting();
94 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, std::move(tracingBackend));
95
96 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
97 ASSERT_EQ(OK, mDispatcher->start());
98 }
99
100 void TearDown() override {
101 ASSERT_EQ(OK, mDispatcher->stop());
102 mDispatcher.reset();
103 mFakePolicy.reset();
104 }
105
106 void waitForTracerIdle() {
107 mDispatcher->waitForIdle();
108 mRequestTracerIdle();
109 }
110
111 void setFocusedWindow(const sp<gui::WindowInfoHandle>& window) {
112 gui::FocusRequest request;
113 request.token = window->getToken();
114 request.windowName = window->getName();
115 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
116 request.displayId = window->getInfo()->displayId;
117 mDispatcher->setFocusedWindow(request);
118 }
119
120 void tapAndExpect(const std::vector<const sp<FakeWindowHandle>>& windows,
121 Level inboundTraceLevel, Level dispatchTraceLevel, InputTraceSession& s) {
122 const auto down = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
123 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(110))
124 .build();
125 mDispatcher->notifyMotion(down);
126 s.expectMotionTraced(inboundTraceLevel, toMotionEvent(down));
127 for (const auto& window : windows) {
128 auto consumed = window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
129 s.expectDispatchTraced(dispatchTraceLevel, {*consumed, window});
130 }
131
132 const auto up = MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
133 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(110))
134 .build();
135 mDispatcher->notifyMotion(up);
136 s.expectMotionTraced(inboundTraceLevel, toMotionEvent(up));
137 for (const auto& window : windows) {
138 auto consumed = window->consumeMotionEvent(WithMotionAction(ACTION_UP));
139 s.expectDispatchTraced(dispatchTraceLevel, {*consumed, window});
140 }
141 }
142
143 void keypressAndExpect(const std::vector<const sp<FakeWindowHandle>>& windows,
144 Level inboundTraceLevel, Level dispatchTraceLevel,
145 InputTraceSession& s) {
146 const auto down = KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build();
147 mDispatcher->notifyKey(down);
148 s.expectKeyTraced(inboundTraceLevel, toKeyEvent(down));
149 for (const auto& window : windows) {
150 auto consumed = window->consumeKeyEvent(WithKeyAction(ACTION_DOWN));
151 s.expectDispatchTraced(dispatchTraceLevel, {*consumed, window});
152 }
153
154 const auto up = KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build();
155 mDispatcher->notifyKey(up);
156 s.expectKeyTraced(inboundTraceLevel, toKeyEvent(up));
157 for (const auto& window : windows) {
158 auto consumed = window->consumeKeyEvent(WithKeyAction(ACTION_UP));
159 s.expectDispatchTraced(dispatchTraceLevel, {*consumed, window});
160 }
161 }
162
163private:
164 std::function<void()> mRequestTracerIdle;
165};
166
167TEST_F(InputTracingTest, EmptyConfigTracesNothing) {
168 InputTraceSession s{[](auto& config) {}};
169
170 auto window = sp<FakeWindowHandle>::make(APP, mDispatcher, "Window", DISPLAY_ID);
171 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
172 setFocusedWindow(window);
173 window->consumeFocusEvent(true);
174
175 tapAndExpect({window}, Level::NONE, Level::NONE, s);
176 keypressAndExpect({window}, Level::NONE, Level::NONE, s);
177
178 waitForTracerIdle();
179}
180
181TEST_F(InputTracingTest, TraceAll) {
182 InputTraceSession s{
183 [](auto& config) { config->set_mode(AndroidInputEventConfig::TRACE_MODE_TRACE_ALL); }};
184
185 auto window = sp<FakeWindowHandle>::make(APP, mDispatcher, "Window", DISPLAY_ID);
186 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
187 setFocusedWindow(window);
188 window->consumeFocusEvent(true);
189
190 tapAndExpect({window}, Level::COMPLETE, Level::COMPLETE, s);
191 keypressAndExpect({window}, Level::COMPLETE, Level::COMPLETE, s);
192
193 waitForTracerIdle();
194}
195
196TEST_F(InputTracingTest, NoRulesTracesNothing) {
197 InputTraceSession s{[](auto& config) {
198 config->set_trace_dispatcher_input_events(true);
199 config->set_trace_dispatcher_window_dispatch(true);
200 config->set_mode(AndroidInputEventConfig::TRACE_MODE_USE_RULES);
201 }};
202
203 auto window = sp<FakeWindowHandle>::make(APP, mDispatcher, "Window", DISPLAY_ID);
204 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
205 setFocusedWindow(window);
206 window->consumeFocusEvent(true);
207
208 tapAndExpect({window}, Level::NONE, Level::NONE, s);
209 keypressAndExpect({window}, Level::NONE, Level::NONE, s);
210
211 waitForTracerIdle();
212}
213
214TEST_F(InputTracingTest, EmptyRuleMatchesEverything) {
215 InputTraceSession s{[](auto& config) {
216 config->set_trace_dispatcher_input_events(true);
217 config->set_trace_dispatcher_window_dispatch(true);
218 config->set_mode(AndroidInputEventConfig::TRACE_MODE_USE_RULES);
219 // Rule: Match everything as COMPLETE
220 auto rule = config->add_rules();
221 rule->set_trace_level(AndroidInputEventConfig::TRACE_LEVEL_COMPLETE);
222 }};
223
224 auto window = sp<FakeWindowHandle>::make(APP, mDispatcher, "Window", DISPLAY_ID);
225 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
226 setFocusedWindow(window);
227 window->consumeFocusEvent(true);
228
229 tapAndExpect({window}, Level::COMPLETE, Level::COMPLETE, s);
230 keypressAndExpect({window}, Level::COMPLETE, Level::COMPLETE, s);
231
232 waitForTracerIdle();
233}
234
235TEST_F(InputTracingTest, UnspecifiedTracelLevel) {
236 InputTraceSession s{[](auto& config) {
237 config->set_trace_dispatcher_input_events(true);
238 config->set_trace_dispatcher_window_dispatch(true);
239 config->set_mode(AndroidInputEventConfig::TRACE_MODE_USE_RULES);
240 // Rule: Match everything, trace level unspecified
241 auto rule = config->add_rules();
242 }};
243
244 auto window = sp<FakeWindowHandle>::make(APP, mDispatcher, "Window", DISPLAY_ID);
245 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
246 setFocusedWindow(window);
247 window->consumeFocusEvent(true);
248
249 // Event is not traced by default if trace level is unspecified
250 tapAndExpect({window}, Level::NONE, Level::NONE, s);
251 keypressAndExpect({window}, Level::NONE, Level::NONE, s);
252
253 waitForTracerIdle();
254}
255
256TEST_F(InputTracingTest, MatchSecureWindow) {
257 InputTraceSession s{[](auto& config) {
258 config->set_trace_dispatcher_input_events(true);
259 config->set_trace_dispatcher_window_dispatch(true);
260 config->set_mode(AndroidInputEventConfig::TRACE_MODE_USE_RULES);
261 // Rule: Match secure windows as COMPLETE
262 auto rule = config->add_rules();
263 rule->set_trace_level(AndroidInputEventConfig::TRACE_LEVEL_COMPLETE);
264 rule->set_match_secure(true);
265 }};
266
267 // Add a normal window and a spy window.
268 auto window = sp<FakeWindowHandle>::make(APP, mDispatcher, "Window", DISPLAY_ID);
269 auto spy = sp<FakeWindowHandle>::make(APP, mDispatcher, "Spy", DISPLAY_ID);
270 spy->setSpy(true);
271 spy->setTrustedOverlay(true);
272 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
273
274 // Since neither are secure windows, events should not be traced.
275 tapAndExpect({spy, window}, Level::NONE, Level::NONE, s);
276
277 // Events should be matched as secure if any of the target windows is marked as secure.
278 spy->setSecure(true);
279 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
280 tapAndExpect({spy, window}, Level::COMPLETE, Level::COMPLETE, s);
281
282 spy->setSecure(false);
283 window->setSecure(true);
284 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
285 tapAndExpect({spy, window}, Level::COMPLETE, Level::COMPLETE, s);
286
287 spy->setSecure(true);
288 window->setSecure(true);
289 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
290 tapAndExpect({spy, window}, Level::COMPLETE, Level::COMPLETE, s);
291
292 spy->setSecure(false);
293 window->setSecure(false);
294 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
295 tapAndExpect({spy, window}, Level::NONE, Level::NONE, s);
296
297 waitForTracerIdle();
298}
299
300TEST_F(InputTracingTest, MatchImeConnectionActive) {
301 InputTraceSession s{[](auto& config) {
302 config->set_trace_dispatcher_input_events(true);
303 config->set_trace_dispatcher_window_dispatch(true);
304 config->set_mode(AndroidInputEventConfig::TRACE_MODE_USE_RULES);
305 // Rule: Match IME Connection Active as COMPLETE
306 auto rule = config->add_rules();
307 rule->set_trace_level(AndroidInputEventConfig::TRACE_LEVEL_COMPLETE);
308 rule->set_match_ime_connection_active(true);
309 }};
310
311 // Add a normal window and a spy window.
312 auto window = sp<FakeWindowHandle>::make(APP, mDispatcher, "Window", DISPLAY_ID);
313 auto spy = sp<FakeWindowHandle>::make(APP, mDispatcher, "Spy", DISPLAY_ID);
314 spy->setSpy(true);
315 spy->setTrustedOverlay(true);
316 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
317
318 // Since IME connection is not active, events should not be traced.
319 tapAndExpect({spy, window}, Level::NONE, Level::NONE, s);
320
321 mDispatcher->setInputMethodConnectionIsActive(true);
322 tapAndExpect({spy, window}, Level::COMPLETE, Level::COMPLETE, s);
323
324 mDispatcher->setInputMethodConnectionIsActive(false);
325 tapAndExpect({spy, window}, Level::NONE, Level::NONE, s);
326
327 waitForTracerIdle();
328}
329
330TEST_F(InputTracingTest, MatchAllPackages) {
331 InputTraceSession s{[](auto& config) {
332 config->set_trace_dispatcher_input_events(true);
333 config->set_trace_dispatcher_window_dispatch(true);
334 config->set_mode(AndroidInputEventConfig::TRACE_MODE_USE_RULES);
335 // Rule: Match all package as COMPLETE
336 auto rule = config->add_rules();
337 rule->set_trace_level(AndroidInputEventConfig::TRACE_LEVEL_COMPLETE);
338 rule->add_match_all_packages(ALLOWED_PKG_1);
339 rule->add_match_all_packages(ALLOWED_PKG_2);
340 }};
341
342 // All windows are allowlisted.
343 auto window = sp<FakeWindowHandle>::make(APP, mDispatcher, "Window", DISPLAY_ID);
344 window->setOwnerInfo(PID, ALLOWED_UID_1);
345 auto spy = sp<FakeWindowHandle>::make(APP, mDispatcher, "Spy", DISPLAY_ID);
346 spy->setOwnerInfo(PID, ALLOWED_UID_2);
347 spy->setSpy(true);
348 spy->setTrustedOverlay(true);
349 auto systemSpy = sp<FakeWindowHandle>::make(APP, mDispatcher, "Spy", DISPLAY_ID);
350 systemSpy->setOwnerInfo(PID, gui::Uid{AID_SYSTEM});
351 systemSpy->setSpy(true);
352 systemSpy->setTrustedOverlay(true);
353 mDispatcher->onWindowInfosChanged(
354 {{*systemSpy->getInfo(), *spy->getInfo(), *window->getInfo()}, {}, 0, 0});
355
356 tapAndExpect({systemSpy, spy, window}, Level::COMPLETE, Level::COMPLETE, s);
357
358 // Add a disallowed spy. This will result in the event not being traced for all windows.
359 auto disallowedSpy = sp<FakeWindowHandle>::make(APP, mDispatcher, "Spy", DISPLAY_ID);
360 disallowedSpy->setOwnerInfo(PID, DISALLOWED_UID_1);
361 disallowedSpy->setSpy(true);
362 disallowedSpy->setTrustedOverlay(true);
363 mDispatcher->onWindowInfosChanged({{*systemSpy->getInfo(), *spy->getInfo(),
364 *disallowedSpy->getInfo(), *window->getInfo()},
365 {},
366 0,
367 0});
368
369 tapAndExpect({systemSpy, spy, disallowedSpy, window}, Level::NONE, Level::NONE, s);
370
371 // Change the owner of the disallowed spy to one for which we don't have a package mapping.
372 disallowedSpy->setOwnerInfo(PID, UNLISTED_UID);
373 mDispatcher->onWindowInfosChanged({{*systemSpy->getInfo(), *spy->getInfo(),
374 *disallowedSpy->getInfo(), *window->getInfo()},
375 {},
376 0,
377 0});
378
379 tapAndExpect({systemSpy, spy, disallowedSpy, window}, Level::NONE, Level::NONE, s);
380
381 // Remove the disallowed spy. Events are traced again.
382 mDispatcher->onWindowInfosChanged(
383 {{*systemSpy->getInfo(), *spy->getInfo(), *window->getInfo()}, {}, 0, 0});
384
385 tapAndExpect({systemSpy, spy, window}, Level::COMPLETE, Level::COMPLETE, s);
386
387 waitForTracerIdle();
388}
389
390TEST_F(InputTracingTest, MatchAnyPackages) {
391 InputTraceSession s{[](auto& config) {
392 config->set_trace_dispatcher_input_events(true);
393 config->set_trace_dispatcher_window_dispatch(true);
394 config->set_mode(AndroidInputEventConfig::TRACE_MODE_USE_RULES);
395 // Rule: Match any package as COMPLETE
396 auto rule = config->add_rules();
397 rule->set_trace_level(AndroidInputEventConfig::TRACE_LEVEL_COMPLETE);
398 rule->add_match_any_packages(ALLOWED_PKG_1);
399 rule->add_match_any_packages(ALLOWED_PKG_2);
400 }};
401
402 // Just a disallowed window. Events are not traced.
403 auto window = sp<FakeWindowHandle>::make(APP, mDispatcher, "Window", DISPLAY_ID);
404 window->setOwnerInfo(PID, DISALLOWED_UID_1);
405 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
406
407 tapAndExpect({window}, Level::NONE, Level::NONE, s);
408
409 // Add a spy for which we don't have a package mapping. Events are still not traced.
410 auto disallowedSpy = sp<FakeWindowHandle>::make(APP, mDispatcher, "Spy", DISPLAY_ID);
411 disallowedSpy->setOwnerInfo(PID, UNLISTED_UID);
412 disallowedSpy->setSpy(true);
413 disallowedSpy->setTrustedOverlay(true);
414 mDispatcher->onWindowInfosChanged({{*disallowedSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
415
416 tapAndExpect({disallowedSpy, window}, Level::NONE, Level::NONE, s);
417
418 // Add an allowed spy. Events are now traced for all packages.
419 auto spy = sp<FakeWindowHandle>::make(APP, mDispatcher, "Spy", DISPLAY_ID);
420 spy->setOwnerInfo(PID, ALLOWED_UID_1);
421 spy->setSpy(true);
422 spy->setTrustedOverlay(true);
423 mDispatcher->onWindowInfosChanged(
424 {{*disallowedSpy->getInfo(), *spy->getInfo(), *window->getInfo()}, {}, 0, 0});
425
426 tapAndExpect({disallowedSpy, spy, window}, Level::COMPLETE, Level::COMPLETE, s);
427
428 // Add another disallowed spy. Events are still traced.
429 auto disallowedSpy2 = sp<FakeWindowHandle>::make(APP, mDispatcher, "Spy", DISPLAY_ID);
430 disallowedSpy2->setOwnerInfo(PID, DISALLOWED_UID_2);
431 disallowedSpy2->setSpy(true);
432 disallowedSpy2->setTrustedOverlay(true);
433 mDispatcher->onWindowInfosChanged({{*disallowedSpy->getInfo(), *disallowedSpy2->getInfo(),
434 *spy->getInfo(), *window->getInfo()},
435 {},
436 0,
437 0});
438
439 tapAndExpect({disallowedSpy, disallowedSpy2, spy, window}, Level::COMPLETE, Level::COMPLETE, s);
440
441 waitForTracerIdle();
442}
443
444TEST_F(InputTracingTest, MultipleMatchersInOneRule) {
445 InputTraceSession s{[](auto& config) {
446 config->set_trace_dispatcher_input_events(true);
447 config->set_trace_dispatcher_window_dispatch(true);
448 config->set_mode(AndroidInputEventConfig::TRACE_MODE_USE_RULES);
449 // Rule: Match all of the following conditions as COMPLETE
450 auto rule = config->add_rules();
451 rule->set_trace_level(AndroidInputEventConfig::TRACE_LEVEL_COMPLETE);
452 rule->add_match_all_packages(ALLOWED_PKG_1);
453 rule->add_match_all_packages(ALLOWED_PKG_2);
454 rule->add_match_any_packages(ALLOWED_PKG_1);
455 rule->add_match_any_packages(DISALLOWED_PKG_1);
456 rule->set_match_secure(false);
457 rule->set_match_ime_connection_active(false);
458 }};
459
460 // A single window into an allowed UID. Matches all matchers.
461 auto window = sp<FakeWindowHandle>::make(APP, mDispatcher, "Window", DISPLAY_ID);
462 window->setOwnerInfo(PID, ALLOWED_UID_1);
463 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
464
465 tapAndExpect({window}, Level::COMPLETE, Level::COMPLETE, s);
466
467 // Secure window does not match.
468 window->setSecure(true);
469 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
470
471 tapAndExpect({window}, Level::NONE, Level::NONE, s);
472
473 // IME Connection Active does not match.
474 window->setSecure(false);
475 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
476 mDispatcher->setInputMethodConnectionIsActive(true);
477
478 tapAndExpect({window}, Level::NONE, Level::NONE, s);
479
480 // Event going to DISALLOWED_PKG_1 does not match because it's not listed in match_all_packages.
481 mDispatcher->setInputMethodConnectionIsActive(false);
482 auto disallowedSpy = sp<FakeWindowHandle>::make(APP, mDispatcher, "Spy", DISPLAY_ID);
483 disallowedSpy->setOwnerInfo(PID, DISALLOWED_UID_1);
484 disallowedSpy->setSpy(true);
485 disallowedSpy->setTrustedOverlay(true);
486 mDispatcher->onWindowInfosChanged({{*disallowedSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
487
488 tapAndExpect({disallowedSpy, window}, Level::NONE, Level::NONE, s);
489
490 // Event going to ALLOWED_PKG_1 does not match because it's not listed in match_any_packages.
491 window->setOwnerInfo(PID, ALLOWED_UID_2);
492 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
493
494 tapAndExpect({window}, Level::NONE, Level::NONE, s);
495
496 // All conditions match.
497 auto spy = sp<FakeWindowHandle>::make(APP, mDispatcher, "Spy", DISPLAY_ID);
498 spy->setOwnerInfo(PID, ALLOWED_UID_1);
499 spy->setSpy(true);
500 spy->setTrustedOverlay(true);
501 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
502
503 tapAndExpect({spy, window}, Level::COMPLETE, Level::COMPLETE, s);
504
505 waitForTracerIdle();
506}
507
508TEST_F(InputTracingTest, MultipleRulesMatchInOrder) {
509 InputTraceSession s{[](auto& config) {
510 config->set_trace_dispatcher_input_events(true);
511 config->set_trace_dispatcher_window_dispatch(true);
512 config->set_mode(AndroidInputEventConfig::TRACE_MODE_USE_RULES);
513 // Rule: Don't trace secure events
514 auto rule1 = config->add_rules();
515 rule1->set_trace_level(AndroidInputEventConfig::TRACE_LEVEL_NONE);
516 rule1->set_match_secure(true);
517 // Rule: Trace matched packages as COMPLETE when IME inactive
518 auto rule2 = config->add_rules();
519 rule2->set_trace_level(AndroidInputEventConfig::TRACE_LEVEL_COMPLETE);
520 rule2->add_match_all_packages(ALLOWED_PKG_1);
521 rule2->add_match_all_packages(ALLOWED_PKG_2);
522 rule2->set_match_ime_connection_active(false);
523 // Rule: Trace the rest of the events as REDACTED
524 auto rule3 = config->add_rules();
525 rule3->set_trace_level(AndroidInputEventConfig::TRACE_LEVEL_REDACTED);
526 }};
527
528 auto window = sp<FakeWindowHandle>::make(APP, mDispatcher, "Window", DISPLAY_ID);
529 window->setOwnerInfo(PID, ALLOWED_UID_1);
530 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
531
532 tapAndExpect({window}, Level::COMPLETE, Level::COMPLETE, s);
533
534 // Verify that the first rule that matches in the order that they are specified is the
535 // one that applies to the event.
536 mDispatcher->setInputMethodConnectionIsActive(true);
537 tapAndExpect({window}, Level::REDACTED, Level::REDACTED, s);
538
539 mDispatcher->setInputMethodConnectionIsActive(false);
540 auto spy = sp<FakeWindowHandle>::make(APP, mDispatcher, "Spy", DISPLAY_ID);
541 spy->setOwnerInfo(PID, ALLOWED_UID_2);
542 spy->setSpy(true);
543 spy->setTrustedOverlay(true);
544 spy->setSecure(true);
545 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
546
547 tapAndExpect({spy, window}, Level::NONE, Level::NONE, s);
548
549 spy->setSecure(false);
550 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
551
552 tapAndExpect({spy, window}, Level::COMPLETE, Level::COMPLETE, s);
553
554 spy->setOwnerInfo(PID, DISALLOWED_UID_1);
555 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
556
557 tapAndExpect({spy, window}, Level::REDACTED, Level::REDACTED, s);
558
559 waitForTracerIdle();
560}
561
562TEST_F(InputTracingTest, TraceInboundEvents) {
563 InputTraceSession s{[](auto& config) {
564 // Only trace inbounds events - don't trace window dispatch
565 config->set_trace_dispatcher_input_events(true);
566 config->set_mode(AndroidInputEventConfig::TRACE_MODE_USE_RULES);
567 // Rule: Trace everything as REDACTED
568 auto rule1 = config->add_rules();
569 rule1->set_trace_level(AndroidInputEventConfig::TRACE_LEVEL_REDACTED);
570 }};
571
572 auto window = sp<FakeWindowHandle>::make(APP, mDispatcher, "Window", DISPLAY_ID);
573 window->setOwnerInfo(PID, ALLOWED_UID_1);
574 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
575
576 // Only the inbound events are traced. No dispatch events are traced.
577 tapAndExpect({window}, Level::REDACTED, Level::NONE, s);
578
579 // Notify a down event, which should be traced.
580 const auto down = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
581 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(110))
582 .build();
583 s.expectMotionTraced(Level::REDACTED, toMotionEvent(down));
584 mDispatcher->notifyMotion(down);
585 auto consumed = window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
586 s.expectDispatchTraced(Level::NONE, {*consumed, window});
587
588 // Force a cancel event to be synthesized. This should not be traced, because only inbound
589 // events are requested.
590 mDispatcher->cancelCurrentTouch();
591 consumed = window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
592 s.expectMotionTraced(Level::NONE, *consumed);
593 s.expectDispatchTraced(Level::NONE, {*consumed, window});
594
595 waitForTracerIdle();
596}
597
598TEST_F(InputTracingTest, TraceWindowDispatch) {
599 InputTraceSession s{[](auto& config) {
600 // Only trace window dispatch - don't trace event details
601 config->set_trace_dispatcher_window_dispatch(true);
602 config->set_mode(AndroidInputEventConfig::TRACE_MODE_USE_RULES);
603 // Rule: Trace everything as REDACTED
604 auto rule1 = config->add_rules();
605 rule1->set_trace_level(AndroidInputEventConfig::TRACE_LEVEL_REDACTED);
606 }};
607
608 auto window = sp<FakeWindowHandle>::make(APP, mDispatcher, "Window", DISPLAY_ID);
609 window->setOwnerInfo(PID, ALLOWED_UID_1);
610 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
611
612 // Only dispatch events are traced. No inbound events are traced.
613 tapAndExpect({window}, Level::NONE, Level::REDACTED, s);
614
615 // Notify a down event; the dispatch should be traced.
616 const auto down = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
617 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(110))
618 .build();
619 s.expectMotionTraced(Level::NONE, toMotionEvent(down));
620 mDispatcher->notifyMotion(down);
621 auto consumed = window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
622 s.expectDispatchTraced(Level::REDACTED, {*consumed, window});
623
624 // Force a cancel event to be synthesized. All events that are dispatched should be traced.
625 mDispatcher->cancelCurrentTouch();
626 consumed = window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
627 s.expectMotionTraced(Level::NONE, *consumed);
628 s.expectDispatchTraced(Level::REDACTED, {*consumed, window});
629}
630
631TEST_F(InputTracingTest, SimultaneousTracingSessions) {
632 auto s1 = std::make_unique<InputTraceSession>(
633 [](auto& config) { config->set_mode(AndroidInputEventConfig::TRACE_MODE_TRACE_ALL); });
634
635 auto window = sp<FakeWindowHandle>::make(APP, mDispatcher, "Window", DISPLAY_ID);
636 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
637 setFocusedWindow(window);
638 window->consumeFocusEvent(true);
639
640 tapAndExpect({window}, Level::COMPLETE, Level::COMPLETE, *s1);
641 keypressAndExpect({window}, Level::COMPLETE, Level::COMPLETE, *s1);
642
643 auto s2 = std::make_unique<InputTraceSession>([](auto& config) {
644 config->set_trace_dispatcher_input_events(true);
645 config->set_trace_dispatcher_window_dispatch(true);
646 config->set_mode(AndroidInputEventConfig::TRACE_MODE_USE_RULES);
647 // Rule: Trace all events as REDACTED when IME inactive
648 auto rule = config->add_rules();
649 rule->set_trace_level(AndroidInputEventConfig::TRACE_LEVEL_REDACTED);
650 rule->set_match_ime_connection_active(false);
651 });
652
653 auto s3 = std::make_unique<InputTraceSession>([](auto& config) {
654 // Only trace window dispatch
655 config->set_trace_dispatcher_window_dispatch(true);
656 config->set_mode(AndroidInputEventConfig::TRACE_MODE_USE_RULES);
657 // Rule: Trace non-secure events as COMPLETE
658 auto rule = config->add_rules();
659 rule->set_trace_level(AndroidInputEventConfig::TRACE_LEVEL_COMPLETE);
660 rule->set_match_secure(false);
661 });
662
663 // Down event should be recorded on all traces.
664 const auto down = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
665 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(110))
666 .build();
667 mDispatcher->notifyMotion(down);
668 s1->expectMotionTraced(Level::COMPLETE, toMotionEvent(down));
669 s2->expectMotionTraced(Level::REDACTED, toMotionEvent(down));
670 s3->expectMotionTraced(Level::NONE, toMotionEvent(down));
671 auto consumed = window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
672 s1->expectDispatchTraced(Level::COMPLETE, {*consumed, window});
673 s2->expectDispatchTraced(Level::REDACTED, {*consumed, window});
674 s3->expectDispatchTraced(Level::COMPLETE, {*consumed, window});
675
676 // Move event when IME is active.
677 mDispatcher->setInputMethodConnectionIsActive(true);
678 const auto move1 = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
679 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(110))
680 .build();
681 mDispatcher->notifyMotion(move1);
682 s1->expectMotionTraced(Level::COMPLETE, toMotionEvent(move1));
683 s2->expectMotionTraced(Level::NONE, toMotionEvent(move1));
684 s3->expectMotionTraced(Level::NONE, toMotionEvent(move1));
685 consumed = window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
686 s1->expectDispatchTraced(Level::COMPLETE, {*consumed, window});
687 s2->expectDispatchTraced(Level::NONE, {*consumed, window});
688 s3->expectDispatchTraced(Level::COMPLETE, {*consumed, window});
689
690 // Move event after window became secure.
691 mDispatcher->setInputMethodConnectionIsActive(false);
692 window->setSecure(true);
693 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
694 const auto move2 = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
695 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(110))
696 .build();
697 mDispatcher->notifyMotion(move2);
698 s1->expectMotionTraced(Level::COMPLETE, toMotionEvent(move2));
699 s2->expectMotionTraced(Level::REDACTED, toMotionEvent(move2));
700 s3->expectMotionTraced(Level::NONE, toMotionEvent(move2));
701 consumed = window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
702 s1->expectDispatchTraced(Level::COMPLETE, {*consumed, window});
703 s2->expectDispatchTraced(Level::REDACTED, {*consumed, window});
704 s3->expectDispatchTraced(Level::NONE, {*consumed, window});
705
706 waitForTracerIdle();
707 s2.reset();
708
709 // Up event.
710 window->setSecure(false);
711 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
712 const auto up = MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
713 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(110))
714 .build();
715 mDispatcher->notifyMotion(up);
716 s1->expectMotionTraced(Level::COMPLETE, toMotionEvent(up));
717 s3->expectMotionTraced(Level::NONE, toMotionEvent(up));
718 consumed = window->consumeMotionEvent(WithMotionAction(ACTION_UP));
719 s1->expectDispatchTraced(Level::COMPLETE, {*consumed, window});
720 s3->expectDispatchTraced(Level::COMPLETE, {*consumed, window});
721
722 waitForTracerIdle();
723 s3.reset();
724
725 tapAndExpect({window}, Level::COMPLETE, Level::COMPLETE, *s1);
726 keypressAndExpect({window}, Level::COMPLETE, Level::COMPLETE, *s1);
727
728 waitForTracerIdle();
729 s1.reset();
730}
731
732} // namespace android::inputdispatcher::trace