• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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