1 /*
2 * Copyright (C) 2025 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/viewcapture_parser.h"
18
19 #include "perfetto/ext/base/base64.h"
20 #include "protos/perfetto/trace/android/viewcapture.pbzero.h"
21 #include "src/trace_processor/importers/common/args_tracker.h"
22 #include "src/trace_processor/tables/winscope_tables_py.h"
23 #include "src/trace_processor/types/trace_processor_context.h"
24 #include "src/trace_processor/util/winscope_proto_mapping.h"
25
26 namespace perfetto {
27 namespace trace_processor {
28
ViewCaptureParser(TraceProcessorContext * context)29 ViewCaptureParser::ViewCaptureParser(TraceProcessorContext* context)
30 : context_{context}, args_parser_{*context->descriptor_pool_} {}
31
Parse(int64_t timestamp,protozero::ConstBytes blob,PacketSequenceStateGeneration * seq_state)32 void ViewCaptureParser::Parse(int64_t timestamp,
33 protozero::ConstBytes blob,
34 PacketSequenceStateGeneration* seq_state) {
35 protos::pbzero::ViewCapture::Decoder snapshot_decoder(blob);
36 tables::ViewCaptureTable::Row row;
37 row.ts = timestamp;
38 row.base64_proto_id = context_->storage->mutable_string_pool()
39 ->InternString(base::StringView(
40 base::Base64Encode(blob.data, blob.size)))
41 .raw_id();
42 auto snapshot_id =
43 context_->storage->mutable_viewcapture_table()->Insert(row).id;
44
45 auto inserter = context_->args_tracker->AddArgsTo(snapshot_id);
46 ViewCaptureArgsParser writer(timestamp, inserter, *context_->storage,
47 seq_state);
48 const auto table_name = tables::ViewCaptureTable::Name();
49 auto allowed_fields =
50 util::winscope_proto_mapping::GetAllowedFields(table_name);
51 base::Status status = args_parser_.ParseMessage(
52 blob, *util::winscope_proto_mapping::GetProtoName(table_name),
53 &allowed_fields.value(), writer);
54
55 AddDeinternedData(writer, row.base64_proto_id.value());
56 if (!status.ok()) {
57 context_->storage->IncrementStats(stats::winscope_viewcapture_parse_errors);
58 }
59 for (auto it = snapshot_decoder.views(); it; ++it) {
60 ParseView(timestamp, *it, snapshot_id, seq_state);
61 }
62 }
63
ParseView(int64_t timestamp,protozero::ConstBytes blob,tables::ViewCaptureTable::Id snapshot_id,PacketSequenceStateGeneration * seq_state)64 void ViewCaptureParser::ParseView(int64_t timestamp,
65 protozero::ConstBytes blob,
66 tables::ViewCaptureTable::Id snapshot_id,
67 PacketSequenceStateGeneration* seq_state) {
68 tables::ViewCaptureViewTable::Row view;
69 view.snapshot_id = snapshot_id;
70 view.base64_proto_id = context_->storage->mutable_string_pool()
71 ->InternString(base::StringView(
72 base::Base64Encode(blob.data, blob.size)))
73 .raw_id();
74 auto layer_id =
75 context_->storage->mutable_viewcapture_view_table()->Insert(view).id;
76
77 ArgsTracker tracker(context_);
78 auto inserter = tracker.AddArgsTo(layer_id);
79 ViewCaptureArgsParser writer(timestamp, inserter, *context_->storage,
80 seq_state);
81 base::Status status =
82 args_parser_.ParseMessage(blob,
83 *util::winscope_proto_mapping::GetProtoName(
84 tables::ViewCaptureViewTable::Name()),
85 nullptr /* parse all fields */, writer);
86
87 AddDeinternedData(writer, view.base64_proto_id.value());
88 if (!status.ok()) {
89 context_->storage->IncrementStats(stats::winscope_viewcapture_parse_errors);
90 }
91 }
92
AddDeinternedData(const ViewCaptureArgsParser & writer,uint32_t base64_proto_id)93 void ViewCaptureParser::AddDeinternedData(const ViewCaptureArgsParser& writer,
94 uint32_t base64_proto_id) {
95 auto* deinterned_data_table =
96 context_->storage->mutable_viewcapture_interned_data_table();
97 for (auto i = writer.flat_key_to_iid_args.GetIterator(); i; ++i) {
98 const auto& flat_key = i.key();
99 ViewCaptureArgsParser::IidToStringMap& iids_to_add = i.value();
100
101 for (auto j = iids_to_add.GetIterator(); j; ++j) {
102 const auto iid = j.key();
103 const auto& deinterned_value = j.value();
104
105 tables::ViewCaptureInternedDataTable::Row interned_data_row;
106 interned_data_row.base64_proto_id = base64_proto_id;
107 interned_data_row.flat_key = flat_key;
108 interned_data_row.iid = static_cast<int64_t>(iid);
109 interned_data_row.deinterned_value = deinterned_value;
110 deinterned_data_table->Insert(interned_data_row);
111 }
112 }
113 }
114
115 } // namespace trace_processor
116 } // namespace perfetto
117