1 /*
2 * Copyright (C) 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 "src/trace_processor/importers/proto/winscope/android_input_event_parser.h"
18
19 #include "perfetto/ext/base/base64.h"
20 #include "protos/perfetto/trace/android/android_input_event.pbzero.h"
21 #include "src/trace_processor/importers/common/args_tracker.h"
22 #include "src/trace_processor/importers/proto/args_parser.h"
23 #include "src/trace_processor/storage/trace_storage.h"
24 #include "src/trace_processor/tables/android_tables_py.h"
25 #include "src/trace_processor/types/trace_processor_context.h"
26 #include "src/trace_processor/util/winscope_proto_mapping.h"
27
28 namespace perfetto::trace_processor {
29
30 using perfetto::protos::pbzero::AndroidInputEvent;
31 using perfetto::protos::pbzero::AndroidKeyEvent;
32 using perfetto::protos::pbzero::AndroidMotionEvent;
33 using perfetto::protos::pbzero::AndroidWindowInputDispatchEvent;
34 using perfetto::protos::pbzero::TracePacket;
35
AndroidInputEventParser(TraceProcessorContext * context)36 AndroidInputEventParser::AndroidInputEventParser(TraceProcessorContext* context)
37 : context_(*context), args_parser_{*context->descriptor_pool_} {}
38
ParseAndroidInputEvent(int64_t packet_ts,const protozero::ConstBytes & bytes)39 void AndroidInputEventParser::ParseAndroidInputEvent(
40 int64_t packet_ts,
41 const protozero::ConstBytes& bytes) {
42 auto input_event = AndroidInputEvent::Decoder(bytes);
43
44 constexpr static auto supported_fields = std::array{
45 AndroidInputEvent::kDispatcherMotionEventFieldNumber,
46 AndroidInputEvent::kDispatcherMotionEventRedactedFieldNumber,
47 AndroidInputEvent::kDispatcherKeyEventFieldNumber,
48 AndroidInputEvent::kDispatcherKeyEventRedactedFieldNumber,
49 AndroidInputEvent::kDispatcherWindowDispatchEventFieldNumber,
50 AndroidInputEvent::kDispatcherWindowDispatchEventRedactedFieldNumber};
51
52 for (auto sub_field_id : supported_fields) {
53 auto sub_field = input_event.Get(static_cast<uint32_t>(sub_field_id));
54 if (!sub_field.valid())
55 continue;
56
57 switch (sub_field_id) {
58 case AndroidInputEvent::kDispatcherMotionEventFieldNumber:
59 case AndroidInputEvent::kDispatcherMotionEventRedactedFieldNumber:
60 ParseMotionEvent(packet_ts, sub_field.as_bytes());
61 return;
62 case AndroidInputEvent::kDispatcherKeyEventFieldNumber:
63 case AndroidInputEvent::kDispatcherKeyEventRedactedFieldNumber:
64 ParseKeyEvent(packet_ts, sub_field.as_bytes());
65 return;
66 case AndroidInputEvent::kDispatcherWindowDispatchEventFieldNumber:
67 case AndroidInputEvent::kDispatcherWindowDispatchEventRedactedFieldNumber:
68 ParseWindowDispatchEvent(packet_ts, sub_field.as_bytes());
69 return;
70 }
71 }
72 }
73
ParseMotionEvent(int64_t packet_ts,const protozero::ConstBytes & bytes)74 void AndroidInputEventParser::ParseMotionEvent(
75 int64_t packet_ts,
76 const protozero::ConstBytes& bytes) {
77 AndroidMotionEvent::Decoder event_proto(bytes);
78 tables::AndroidMotionEventsTable::Row event_row;
79 event_row.event_id = event_proto.event_id();
80 event_row.ts = packet_ts;
81 event_row.base64_proto_id =
82 context_.storage->mutable_string_pool()
83 ->InternString(
84 base::StringView(base::Base64Encode(bytes.data, bytes.size)))
85 .raw_id();
86
87 auto event_row_id = context_.storage->mutable_android_motion_events_table()
88 ->Insert(event_row)
89 .id;
90 auto inserter = context_.args_tracker->AddArgsTo(event_row_id);
91 ArgsParser writer{packet_ts, inserter, *context_.storage};
92
93 base::Status status =
94 args_parser_.ParseMessage(bytes,
95 *util::winscope_proto_mapping::GetProtoName(
96 tables::AndroidMotionEventsTable::Name()),
97 nullptr /*parse all fields*/, writer);
98 if (!status.ok())
99 context_.storage->IncrementStats(stats::android_input_event_parse_errors);
100 }
101
ParseKeyEvent(int64_t packet_ts,const protozero::ConstBytes & bytes)102 void AndroidInputEventParser::ParseKeyEvent(
103 int64_t packet_ts,
104 const protozero::ConstBytes& bytes) {
105 AndroidKeyEvent::Decoder event_proto(bytes);
106 tables::AndroidKeyEventsTable::Row event_row;
107 event_row.event_id = event_proto.event_id();
108 event_row.ts = packet_ts;
109 event_row.base64_proto_id =
110 context_.storage->mutable_string_pool()
111 ->InternString(
112 base::StringView(base::Base64Encode(bytes.data, bytes.size)))
113 .raw_id();
114
115 auto event_row_id = context_.storage->mutable_android_key_events_table()
116 ->Insert(event_row)
117 .id;
118 auto inserter = context_.args_tracker->AddArgsTo(event_row_id);
119 ArgsParser writer{packet_ts, inserter, *context_.storage};
120
121 base::Status status =
122 args_parser_.ParseMessage(bytes,
123 *util::winscope_proto_mapping::GetProtoName(
124 tables::AndroidKeyEventsTable::Name()),
125 nullptr /*parse all fields*/, writer);
126 if (!status.ok())
127 context_.storage->IncrementStats(stats::android_input_event_parse_errors);
128 }
129
ParseWindowDispatchEvent(int64_t packet_ts,const protozero::ConstBytes & bytes)130 void AndroidInputEventParser::ParseWindowDispatchEvent(
131 int64_t packet_ts,
132 const protozero::ConstBytes& bytes) {
133 AndroidWindowInputDispatchEvent::Decoder event_proto(bytes);
134 tables::AndroidInputEventDispatchTable::Row event_row;
135 event_row.event_id = event_proto.event_id();
136 event_row.vsync_id = event_proto.vsync_id();
137 event_row.window_id = event_proto.window_id();
138 event_row.base64_proto_id =
139 context_.storage->mutable_string_pool()
140 ->InternString(
141 base::StringView(base::Base64Encode(bytes.data, bytes.size)))
142 .raw_id();
143
144 auto event_row_id =
145 context_.storage->mutable_android_input_event_dispatch_table()
146 ->Insert(event_row)
147 .id;
148
149 auto inserter = context_.args_tracker->AddArgsTo(event_row_id);
150 ArgsParser writer{packet_ts, inserter, *context_.storage};
151
152 base::Status status = args_parser_.ParseMessage(
153 bytes,
154 *util::winscope_proto_mapping::GetProtoName(
155 tables::AndroidInputEventDispatchTable::Name()),
156 nullptr /*parse all fields*/, writer);
157 if (!status.ok())
158 context_.storage->IncrementStats(stats::android_input_event_parse_errors);
159 }
160
161 } // namespace perfetto::trace_processor
162