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