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/viewcapture_args_parser.h"
18 #include "perfetto/ext/base/string_utils.h"
19 #include "perfetto/ext/base/string_view.h"
20 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
21 #include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
22 #include "src/trace_processor/importers/proto/packet_sequence_state_generation.h"
23
24 namespace perfetto {
25 namespace trace_processor {
26
ViewCaptureArgsParser(int64_t packet_timestamp,ArgsTracker::BoundInserter & inserter,TraceStorage & storage,PacketSequenceStateGeneration * sequence_state)27 ViewCaptureArgsParser::ViewCaptureArgsParser(
28 int64_t packet_timestamp,
29 ArgsTracker::BoundInserter& inserter,
30 TraceStorage& storage,
31 PacketSequenceStateGeneration* sequence_state)
32 : ArgsParser(packet_timestamp, inserter, storage, sequence_state),
33 storage_{storage} {}
34
AddInteger(const Key & key,int64_t value)35 void ViewCaptureArgsParser::AddInteger(const Key& key, int64_t value) {
36 if (TryAddDeinternedString(key, static_cast<uint64_t>(value))) {
37 return;
38 }
39 ArgsParser::AddInteger(key, value);
40 }
41
AddUnsignedInteger(const Key & key,uint64_t value)42 void ViewCaptureArgsParser::AddUnsignedInteger(const Key& key, uint64_t value) {
43 if (TryAddDeinternedString(key, value)) {
44 return;
45 }
46 ArgsParser::AddUnsignedInteger(key, value);
47 }
48
TryAddDeinternedString(const Key & key,uint64_t iid)49 bool ViewCaptureArgsParser::TryAddDeinternedString(const Key& key,
50 uint64_t iid) {
51 bool is_interned_field = base::EndsWith(key.key, "_iid");
52 if (!is_interned_field) {
53 return false;
54 }
55
56 const auto deintern_key = key.key.substr(0, key.key.size() - 4);
57 const auto deintern_flat_key =
58 key.flat_key.substr(0, key.flat_key.size() - 4);
59 const auto deintern_key_combined = Key{deintern_flat_key, deintern_key};
60 const auto deintern_val = TryDeinternString(key, iid);
61
62 if (!deintern_val) {
63 ArgsParser::AddString(
64 deintern_key_combined,
65 protozero::ConstChars{ERROR_MSG.data(), ERROR_MSG.size()});
66 storage_.IncrementStats(
67 stats::winscope_viewcapture_missing_interned_string_parse_errors);
68 return false;
69 }
70
71 ArgsParser::AddString(deintern_key_combined, *deintern_val);
72 return true;
73 }
74
TryDeinternString(const Key & key,uint64_t iid)75 std::optional<protozero::ConstChars> ViewCaptureArgsParser::TryDeinternString(
76 const Key& key,
77 uint64_t iid) {
78 if (base::EndsWith(key.key, "class_name_iid")) {
79 auto* decoder =
80 seq_state()
81 ->LookupInternedMessage<
82 protos::pbzero::InternedData::kViewcaptureClassNameFieldNumber,
83 protos::pbzero::InternedString>(iid);
84 if (decoder) {
85 return protozero::ConstChars{
86 reinterpret_cast<const char*>(decoder->str().data),
87 decoder->str().size};
88 }
89 } else if (base::EndsWith(key.key, "package_name_iid")) {
90 auto* decoder =
91 seq_state()
92 ->LookupInternedMessage<protos::pbzero::InternedData::
93 kViewcapturePackageNameFieldNumber,
94 protos::pbzero::InternedString>(iid);
95 if (decoder) {
96 return protozero::ConstChars{
97 reinterpret_cast<const char*>(decoder->str().data),
98 decoder->str().size};
99 }
100 } else if (base::EndsWith(key.key, "view_id_iid")) {
101 auto* decoder =
102 seq_state()
103 ->LookupInternedMessage<
104 protos::pbzero::InternedData::kViewcaptureViewIdFieldNumber,
105 protos::pbzero::InternedString>(iid);
106 if (decoder) {
107 return protozero::ConstChars{
108 reinterpret_cast<const char*>(decoder->str().data),
109 decoder->str().size};
110 }
111 } else if (base::EndsWith(key.key, "window_name_iid")) {
112 auto* decoder =
113 seq_state()
114 ->LookupInternedMessage<
115 protos::pbzero::InternedData::kViewcaptureWindowNameFieldNumber,
116 protos::pbzero::InternedString>(iid);
117 if (decoder) {
118 return protozero::ConstChars{
119 reinterpret_cast<const char*>(decoder->str().data),
120 decoder->str().size};
121 }
122 }
123
124 return std::nullopt;
125 }
126
127 } // namespace trace_processor
128 } // namespace perfetto
129