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 =
82 context_.storage->mutable_string_pool()->InternString(
83 base::StringView(base::Base64Encode(bytes.data, bytes.size)));
84 event_row.base64_proto_id = event_row.base64_proto.raw_id();
85
86 auto event_row_id = context_.storage->mutable_android_motion_events_table()
87 ->Insert(event_row)
88 .id;
89 auto inserter = context_.args_tracker->AddArgsTo(event_row_id);
90 ArgsParser writer{packet_ts, inserter, *context_.storage};
91
92 base::Status status =
93 args_parser_.ParseMessage(bytes,
94 *util::winscope_proto_mapping::GetProtoName(
95 tables::AndroidMotionEventsTable::Name()),
96 nullptr /*parse all fields*/, writer);
97 if (!status.ok())
98 context_.storage->IncrementStats(stats::android_input_event_parse_errors);
99 }
100
ParseKeyEvent(int64_t packet_ts,const protozero::ConstBytes & bytes)101 void AndroidInputEventParser::ParseKeyEvent(
102 int64_t packet_ts,
103 const protozero::ConstBytes& bytes) {
104 AndroidKeyEvent::Decoder event_proto(bytes);
105 tables::AndroidKeyEventsTable::Row event_row;
106 event_row.event_id = event_proto.event_id();
107 event_row.ts = packet_ts;
108 event_row.base64_proto =
109 context_.storage->mutable_string_pool()->InternString(
110 base::StringView(base::Base64Encode(bytes.data, bytes.size)));
111 event_row.base64_proto_id = event_row.base64_proto.raw_id();
112
113 auto event_row_id = context_.storage->mutable_android_key_events_table()
114 ->Insert(event_row)
115 .id;
116 auto inserter = context_.args_tracker->AddArgsTo(event_row_id);
117 ArgsParser writer{packet_ts, inserter, *context_.storage};
118
119 base::Status status =
120 args_parser_.ParseMessage(bytes,
121 *util::winscope_proto_mapping::GetProtoName(
122 tables::AndroidKeyEventsTable::Name()),
123 nullptr /*parse all fields*/, writer);
124 if (!status.ok())
125 context_.storage->IncrementStats(stats::android_input_event_parse_errors);
126 }
127
ParseWindowDispatchEvent(int64_t packet_ts,const protozero::ConstBytes & bytes)128 void AndroidInputEventParser::ParseWindowDispatchEvent(
129 int64_t packet_ts,
130 const protozero::ConstBytes& bytes) {
131 AndroidWindowInputDispatchEvent::Decoder event_proto(bytes);
132 tables::AndroidInputEventDispatchTable::Row event_row;
133 event_row.event_id = event_proto.event_id();
134 event_row.vsync_id = event_proto.vsync_id();
135 event_row.window_id = event_proto.window_id();
136 event_row.base64_proto =
137 context_.storage->mutable_string_pool()->InternString(
138 base::StringView(base::Base64Encode(bytes.data, bytes.size)));
139 event_row.base64_proto_id = event_row.base64_proto.raw_id();
140
141 auto event_row_id =
142 context_.storage->mutable_android_input_event_dispatch_table()
143 ->Insert(event_row)
144 .id;
145
146 auto inserter = context_.args_tracker->AddArgsTo(event_row_id);
147 ArgsParser writer{packet_ts, inserter, *context_.storage};
148
149 base::Status status = args_parser_.ParseMessage(
150 bytes,
151 *util::winscope_proto_mapping::GetProtoName(
152 tables::AndroidInputEventDispatchTable::Name()),
153 nullptr /*parse all fields*/, writer);
154 if (!status.ok())
155 context_.storage->IncrementStats(stats::android_input_event_parse_errors);
156 }
157
158 } // namespace perfetto::trace_processor
159