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