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