1 /*
2 * Copyright (C) 2023 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/winscope_module.h"
18
19 #include <cstdint>
20
21 #include "perfetto/base/status.h"
22 #include "perfetto/ext/base/base64.h"
23 #include "perfetto/ext/base/flat_hash_map.h"
24 #include "perfetto/ext/base/string_view.h"
25 #include "perfetto/protozero/field.h"
26 #include "perfetto/trace_processor/ref_counted.h"
27 #include "protos/perfetto/trace/android/winscope_extensions.pbzero.h"
28 #include "protos/perfetto/trace/android/winscope_extensions_impl.pbzero.h"
29 #include "src/trace_processor/importers/common/args_tracker.h"
30 #include "src/trace_processor/importers/common/parser_types.h"
31 #include "src/trace_processor/importers/proto/args_parser.h"
32 #include "src/trace_processor/importers/proto/packet_sequence_state_generation.h"
33 #include "src/trace_processor/importers/proto/proto_importer_module.h"
34 #include "src/trace_processor/importers/proto/winscope/viewcapture_args_parser.h"
35 #include "src/trace_processor/importers/proto/winscope/winscope.descriptor.h"
36 #include "src/trace_processor/storage/stats.h"
37 #include "src/trace_processor/tables/winscope_tables_py.h"
38 #include "src/trace_processor/util/winscope_proto_mapping.h"
39
40 namespace perfetto::trace_processor {
41
42 using perfetto::protos::pbzero::TracePacket;
43 using perfetto::protos::pbzero::WinscopeExtensionsImpl;
44
WinscopeModule(TraceProcessorContext * context)45 WinscopeModule::WinscopeModule(TraceProcessorContext* context)
46 : context_{context},
47 args_parser_{*context->descriptor_pool_},
48 surfaceflinger_layers_parser_(context),
49 surfaceflinger_transactions_parser_(context),
50 shell_transitions_parser_(context),
51 protolog_parser_(context),
52 android_input_event_parser_(context),
53 viewcapture_parser_(context) {
54 context->descriptor_pool_->AddFromFileDescriptorSet(
55 kWinscopeDescriptor.data(), kWinscopeDescriptor.size());
56 RegisterForField(TracePacket::kSurfaceflingerLayersSnapshotFieldNumber,
57 context);
58 RegisterForField(TracePacket::kSurfaceflingerTransactionsFieldNumber,
59 context);
60 RegisterForField(TracePacket::kShellTransitionFieldNumber, context);
61 RegisterForField(TracePacket::kShellHandlerMappingsFieldNumber, context);
62 RegisterForField(TracePacket::kProtologMessageFieldNumber, context);
63 RegisterForField(TracePacket::kProtologViewerConfigFieldNumber, context);
64 RegisterForField(TracePacket::kWinscopeExtensionsFieldNumber, context);
65 }
66
TokenizePacket(const protos::pbzero::TracePacket::Decoder & decoder,TraceBlobView *,int64_t,RefPtr<PacketSequenceStateGeneration>,uint32_t field_id)67 ModuleResult WinscopeModule::TokenizePacket(
68 const protos::pbzero::TracePacket::Decoder& decoder,
69 TraceBlobView* /*packet*/,
70 int64_t /*packet_timestamp*/,
71 RefPtr<PacketSequenceStateGeneration> /*state*/,
72 uint32_t field_id) {
73 switch (field_id) {
74 case TracePacket::kProtologViewerConfigFieldNumber:
75 protolog_parser_.ParseAndAddViewerConfigToMessageDecoder(
76 decoder.protolog_viewer_config());
77 return ModuleResult::Handled();
78 }
79
80 return ModuleResult::Ignored();
81 }
82
ParseTracePacketData(const TracePacket::Decoder & decoder,int64_t timestamp,const TracePacketData & data,uint32_t field_id)83 void WinscopeModule::ParseTracePacketData(const TracePacket::Decoder& decoder,
84 int64_t timestamp,
85 const TracePacketData& data,
86 uint32_t field_id) {
87 switch (field_id) {
88 case TracePacket::kSurfaceflingerLayersSnapshotFieldNumber:
89 surfaceflinger_layers_parser_.Parse(
90 timestamp, decoder.surfaceflinger_layers_snapshot());
91 return;
92 case TracePacket::kSurfaceflingerTransactionsFieldNumber:
93 surfaceflinger_transactions_parser_.Parse(
94 timestamp, decoder.surfaceflinger_transactions());
95 return;
96 case TracePacket::kShellTransitionFieldNumber:
97 shell_transitions_parser_.ParseTransition(decoder.shell_transition());
98 return;
99 case TracePacket::kShellHandlerMappingsFieldNumber:
100 shell_transitions_parser_.ParseHandlerMappings(
101 decoder.shell_handler_mappings());
102 return;
103 case TracePacket::kProtologMessageFieldNumber:
104 protolog_parser_.ParseProtoLogMessage(
105 data.sequence_state.get(), decoder.protolog_message(), timestamp);
106 return;
107 case TracePacket::kWinscopeExtensionsFieldNumber:
108 ParseWinscopeExtensionsData(decoder.winscope_extensions(), timestamp,
109 data);
110 return;
111 }
112 }
113
ParseWinscopeExtensionsData(protozero::ConstBytes blob,int64_t timestamp,const TracePacketData & data)114 void WinscopeModule::ParseWinscopeExtensionsData(protozero::ConstBytes blob,
115 int64_t timestamp,
116 const TracePacketData& data) {
117 WinscopeExtensionsImpl::Decoder decoder(blob.data, blob.size);
118
119 if (auto field =
120 decoder.Get(WinscopeExtensionsImpl::kInputmethodClientsFieldNumber);
121 field.valid()) {
122 ParseInputMethodClientsData(timestamp, field.as_bytes());
123 } else if (field = decoder.Get(
124 WinscopeExtensionsImpl::kInputmethodManagerServiceFieldNumber);
125 field.valid()) {
126 ParseInputMethodManagerServiceData(timestamp, field.as_bytes());
127 } else if (field = decoder.Get(
128 WinscopeExtensionsImpl::kInputmethodServiceFieldNumber);
129 field.valid()) {
130 ParseInputMethodServiceData(timestamp, field.as_bytes());
131 } else if (field =
132 decoder.Get(WinscopeExtensionsImpl::kViewcaptureFieldNumber);
133 field.valid()) {
134 viewcapture_parser_.Parse(timestamp, field.as_bytes(),
135 data.sequence_state.get());
136 } else if (field = decoder.Get(
137 WinscopeExtensionsImpl::kAndroidInputEventFieldNumber);
138 field.valid()) {
139 android_input_event_parser_.ParseAndroidInputEvent(timestamp,
140 field.as_bytes());
141 } else if (field =
142 decoder.Get(WinscopeExtensionsImpl::kWindowmanagerFieldNumber);
143 field.valid()) {
144 ParseWindowManagerData(timestamp, field.as_bytes());
145 }
146 }
147
ParseInputMethodClientsData(int64_t timestamp,protozero::ConstBytes blob)148 void WinscopeModule::ParseInputMethodClientsData(int64_t timestamp,
149 protozero::ConstBytes blob) {
150 tables::InputMethodClientsTable::Row row;
151 row.ts = timestamp;
152 row.base64_proto_id = context_->storage->mutable_string_pool()
153 ->InternString(base::StringView(
154 base::Base64Encode(blob.data, blob.size)))
155 .raw_id();
156 auto rowId =
157 context_->storage->mutable_inputmethod_clients_table()->Insert(row).id;
158
159 ArgsTracker tracker(context_);
160 auto inserter = tracker.AddArgsTo(rowId);
161 ArgsParser writer(timestamp, inserter, *context_->storage);
162 base::Status status =
163 args_parser_.ParseMessage(blob,
164 *util::winscope_proto_mapping::GetProtoName(
165 tables::InputMethodClientsTable::Name()),
166 nullptr /* parse all fields */, writer);
167 if (!status.ok()) {
168 context_->storage->IncrementStats(
169 stats::winscope_inputmethod_clients_parse_errors);
170 }
171 }
172
ParseInputMethodManagerServiceData(int64_t timestamp,protozero::ConstBytes blob)173 void WinscopeModule::ParseInputMethodManagerServiceData(
174 int64_t timestamp,
175 protozero::ConstBytes blob) {
176 tables::InputMethodManagerServiceTable::Row row;
177 row.ts = timestamp;
178 row.base64_proto_id = context_->storage->mutable_string_pool()
179 ->InternString(base::StringView(
180 base::Base64Encode(blob.data, blob.size)))
181 .raw_id();
182 auto rowId = context_->storage->mutable_inputmethod_manager_service_table()
183 ->Insert(row)
184 .id;
185
186 ArgsTracker tracker(context_);
187 auto inserter = tracker.AddArgsTo(rowId);
188 ArgsParser writer(timestamp, inserter, *context_->storage);
189 base::Status status = args_parser_.ParseMessage(
190 blob,
191 *util::winscope_proto_mapping::GetProtoName(
192 tables::InputMethodManagerServiceTable::Name()),
193 nullptr /* parse all fields */, writer);
194 if (!status.ok()) {
195 context_->storage->IncrementStats(
196 stats::winscope_inputmethod_manager_service_parse_errors);
197 }
198 }
199
ParseInputMethodServiceData(int64_t timestamp,protozero::ConstBytes blob)200 void WinscopeModule::ParseInputMethodServiceData(int64_t timestamp,
201 protozero::ConstBytes blob) {
202 tables::InputMethodServiceTable::Row row;
203 row.ts = timestamp;
204 row.base64_proto_id = context_->storage->mutable_string_pool()
205 ->InternString(base::StringView(
206 base::Base64Encode(blob.data, blob.size)))
207 .raw_id();
208 auto rowId =
209 context_->storage->mutable_inputmethod_service_table()->Insert(row).id;
210
211 ArgsTracker tracker(context_);
212 auto inserter = tracker.AddArgsTo(rowId);
213 ArgsParser writer(timestamp, inserter, *context_->storage);
214 base::Status status =
215 args_parser_.ParseMessage(blob,
216 *util::winscope_proto_mapping::GetProtoName(
217 tables::InputMethodServiceTable::Name()),
218 nullptr /* parse all fields */, writer);
219 if (!status.ok()) {
220 context_->storage->IncrementStats(
221 stats::winscope_inputmethod_service_parse_errors);
222 }
223 }
224
ParseWindowManagerData(int64_t timestamp,protozero::ConstBytes blob)225 void WinscopeModule::ParseWindowManagerData(int64_t timestamp,
226 protozero::ConstBytes blob) {
227 tables::WindowManagerTable::Row row;
228 row.ts = timestamp;
229 row.base64_proto_id = context_->storage->mutable_string_pool()
230 ->InternString(base::StringView(
231 base::Base64Encode(blob.data, blob.size)))
232 .raw_id();
233 auto rowId = context_->storage->mutable_windowmanager_table()->Insert(row).id;
234
235 ArgsTracker tracker(context_);
236 auto inserter = tracker.AddArgsTo(rowId);
237 ArgsParser writer(timestamp, inserter, *context_->storage);
238 base::Status status =
239 args_parser_.ParseMessage(blob,
240 *util::winscope_proto_mapping::GetProtoName(
241 tables::WindowManagerTable::Name()),
242 nullptr /* parse all fields */, writer);
243 if (!status.ok()) {
244 context_->storage->IncrementStats(
245 stats::winscope_windowmanager_parse_errors);
246 }
247 }
248
249 } // namespace perfetto::trace_processor
250