InputTracer: Distinguish sensitive events
There are three levels of tracing: complete, redacted, and none.
Write events that are redacted into a separate proto, while also
omitting certain fields from being written.
The redacted level will be used in subsequent CLs.
Bug: 210460522
Test: manual with perfetto
Change-Id: Ie65e7915c3aa5fc972e675c43e46970363bab3a4
diff --git a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp
index ddc4cb3..c431fb7 100644
--- a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp
+++ b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp
@@ -39,7 +39,8 @@
} // namespace
void AndroidInputEventProtoConverter::toProtoMotionEvent(const TracedMotionEvent& event,
- proto::AndroidMotionEvent& outProto) {
+ proto::AndroidMotionEvent& outProto,
+ bool isRedacted) {
outProto.set_event_id(event.id);
outProto.set_event_time_nanos(event.eventTime);
outProto.set_down_time_nanos(event.downTime);
@@ -48,11 +49,15 @@
outProto.set_device_id(event.deviceId);
outProto.set_display_id(event.displayId);
outProto.set_classification(static_cast<int32_t>(event.classification));
- outProto.set_cursor_position_x(event.xCursorPosition);
- outProto.set_cursor_position_y(event.yCursorPosition);
outProto.set_flags(event.flags);
outProto.set_policy_flags(event.policyFlags);
+ if (!isRedacted) {
+ outProto.set_cursor_position_x(event.xCursorPosition);
+ outProto.set_cursor_position_y(event.yCursorPosition);
+ outProto.set_meta_state(event.metaState);
+ }
+
for (uint32_t i = 0; i < event.pointerProperties.size(); i++) {
auto* pointer = outProto.add_pointer();
@@ -66,13 +71,17 @@
const auto axis = bits.clearFirstMarkedBit();
auto axisEntry = pointer->add_axis_value();
axisEntry->set_axis(axis);
- axisEntry->set_value(coords.values[axisIndex]);
+
+ if (!isRedacted) {
+ axisEntry->set_value(coords.values[axisIndex]);
+ }
}
}
}
void AndroidInputEventProtoConverter::toProtoKeyEvent(const TracedKeyEvent& event,
- proto::AndroidKeyEvent& outProto) {
+ proto::AndroidKeyEvent& outProto,
+ bool isRedacted) {
outProto.set_event_id(event.id);
outProto.set_event_time_nanos(event.eventTime);
outProto.set_down_time_nanos(event.downTime);
@@ -80,21 +89,28 @@
outProto.set_action(event.action);
outProto.set_device_id(event.deviceId);
outProto.set_display_id(event.displayId);
- outProto.set_key_code(event.keyCode);
- outProto.set_scan_code(event.scanCode);
- outProto.set_meta_state(event.metaState);
outProto.set_repeat_count(event.repeatCount);
outProto.set_flags(event.flags);
outProto.set_policy_flags(event.policyFlags);
+
+ if (!isRedacted) {
+ outProto.set_key_code(event.keyCode);
+ outProto.set_scan_code(event.scanCode);
+ outProto.set_meta_state(event.metaState);
+ }
}
void AndroidInputEventProtoConverter::toProtoWindowDispatchEvent(
- const WindowDispatchArgs& args, proto::AndroidWindowInputDispatchEvent& outProto) {
+ const WindowDispatchArgs& args, proto::AndroidWindowInputDispatchEvent& outProto,
+ bool isRedacted) {
std::visit([&](auto entry) { outProto.set_event_id(entry.id); }, args.eventEntry);
outProto.set_vsync_id(args.vsyncId);
outProto.set_window_id(args.windowId);
outProto.set_resolved_flags(args.resolvedFlags);
+ if (isRedacted) {
+ return;
+ }
if (auto* motion = std::get_if<TracedMotionEvent>(&args.eventEntry); motion != nullptr) {
for (size_t i = 0; i < motion->pointerProperties.size(); i++) {
auto* pointerProto = outProto.add_dispatched_pointer();
diff --git a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h
index bab1701..887913f 100644
--- a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h
+++ b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h
@@ -32,10 +32,12 @@
class AndroidInputEventProtoConverter {
public:
static void toProtoMotionEvent(const TracedMotionEvent& event,
- proto::AndroidMotionEvent& outProto);
- static void toProtoKeyEvent(const TracedKeyEvent& event, proto::AndroidKeyEvent& outProto);
+ proto::AndroidMotionEvent& outProto, bool isRedacted);
+ static void toProtoKeyEvent(const TracedKeyEvent& event, proto::AndroidKeyEvent& outProto,
+ bool isRedacted);
static void toProtoWindowDispatchEvent(const WindowDispatchArgs&,
- proto::AndroidWindowInputDispatchEvent& outProto);
+ proto::AndroidWindowInputDispatchEvent& outProto,
+ bool isRedacted);
static impl::TraceConfig parseConfig(proto::AndroidInputEventConfig::Decoder& protoConfig);
};
diff --git a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp
index 998ec8a..bed753c 100644
--- a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp
+++ b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp
@@ -69,6 +69,30 @@
return false;
}
+TraceLevel PerfettoBackend::InputEventDataSource::resolveTraceLevel(
+ const TracedEventArgs& args) const {
+ // Check for matches with the rules in the order that they are defined.
+ for (const auto& rule : mConfig.rules) {
+ if (ruleMatches(rule, args)) {
+ return rule.level;
+ }
+ }
+
+ // The event is not traced if it matched zero rules.
+ return TraceLevel::TRACE_LEVEL_NONE;
+}
+
+bool PerfettoBackend::InputEventDataSource::ruleMatches(const TraceRule& rule,
+ const TracedEventArgs& args) const {
+ // By default, a rule will match all events. Return early if the rule does not match.
+
+ if (rule.matchSecure.has_value() && *rule.matchSecure != args.isSecure) {
+ return false;
+ }
+
+ return true;
+}
+
// --- PerfettoBackend ---
std::once_flag PerfettoBackend::sDataSourceRegistrationFlag{};
@@ -94,54 +118,62 @@
void PerfettoBackend::traceMotionEvent(const TracedMotionEvent& event,
const TracedEventArgs& args) {
- if (args.isSecure) {
- // For now, avoid tracing secure event entirely.
- return;
- }
InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
auto dataSource = ctx.GetDataSourceLocked();
if (dataSource->shouldIgnoreTracedInputEvent(event.eventType)) {
return;
}
+ const TraceLevel traceLevel = dataSource->resolveTraceLevel(args);
+ if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) {
+ return;
+ }
+ const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED;
auto tracePacket = ctx.NewTracePacket();
auto* inputEvent = tracePacket->set_android_input_event();
- auto* dispatchMotion = inputEvent->set_dispatcher_motion_event();
- AndroidInputEventProtoConverter::toProtoMotionEvent(event, *dispatchMotion);
+ auto* dispatchMotion = isRedacted ? inputEvent->set_dispatcher_motion_event_redacted()
+ : inputEvent->set_dispatcher_motion_event();
+ AndroidInputEventProtoConverter::toProtoMotionEvent(event, *dispatchMotion, isRedacted);
});
}
void PerfettoBackend::traceKeyEvent(const TracedKeyEvent& event, const TracedEventArgs& args) {
- if (args.isSecure) {
- // For now, avoid tracing secure event entirely.
- return;
- }
InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
auto dataSource = ctx.GetDataSourceLocked();
if (dataSource->shouldIgnoreTracedInputEvent(event.eventType)) {
return;
}
+ const TraceLevel traceLevel = dataSource->resolveTraceLevel(args);
+ if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) {
+ return;
+ }
+ const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED;
auto tracePacket = ctx.NewTracePacket();
auto* inputEvent = tracePacket->set_android_input_event();
- auto* dispatchKey = inputEvent->set_dispatcher_key_event();
- AndroidInputEventProtoConverter::toProtoKeyEvent(event, *dispatchKey);
+ auto* dispatchKey = isRedacted ? inputEvent->set_dispatcher_key_event_redacted()
+ : inputEvent->set_dispatcher_key_event();
+ AndroidInputEventProtoConverter::toProtoKeyEvent(event, *dispatchKey, isRedacted);
});
}
void PerfettoBackend::traceWindowDispatch(const WindowDispatchArgs& dispatchArgs,
const TracedEventArgs& args) {
- if (args.isSecure) {
- // For now, avoid tracing secure event entirely.
- return;
- }
InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
auto dataSource = ctx.GetDataSourceLocked();
if (!dataSource->getFlags().test(TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH)) {
return;
}
+ const TraceLevel traceLevel = dataSource->resolveTraceLevel(args);
+ if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) {
+ return;
+ }
+ const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED;
auto tracePacket = ctx.NewTracePacket();
auto* inputEvent = tracePacket->set_android_input_event();
- auto* dispatchEvent = inputEvent->set_dispatcher_window_dispatch_event();
- AndroidInputEventProtoConverter::toProtoWindowDispatchEvent(dispatchArgs, *dispatchEvent);
+ auto* dispatchEvent = isRedacted
+ ? inputEvent->set_dispatcher_window_dispatch_event_redacted()
+ : inputEvent->set_dispatcher_window_dispatch_event();
+ AndroidInputEventProtoConverter::toProtoWindowDispatchEvent(dispatchArgs, *dispatchEvent,
+ isRedacted);
});
}
diff --git a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.h b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.h
index 920ea60..c4f80c3 100644
--- a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.h
+++ b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.h
@@ -68,10 +68,13 @@
bool shouldIgnoreTracedInputEvent(const EventType&) const;
inline ftl::Flags<TraceFlag> getFlags() const { return mConfig.flags; }
+ TraceLevel resolveTraceLevel(const TracedEventArgs&) const;
private:
const int32_t mInstanceId;
TraceConfig mConfig;
+
+ bool ruleMatches(const TraceRule&, const TracedEventArgs&) const;
};
static std::once_flag sDataSourceRegistrationFlag;