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