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