1
2 /*
3 * Copyright (C) 2022 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <cinttypes>
19 #include <cstdint>
20 #include <memory>
21
22 #include "perfetto/base/logging.h"
23 #include "perfetto/ext/base/string_utils.h"
24 #include "perfetto/protozero/field.h"
25 #include "src/trace_processor/importers/common/args_tracker.h"
26 #include "src/trace_processor/importers/common/slice_tracker.h"
27 #include "src/trace_processor/importers/common/track_compressor.h"
28 #include "src/trace_processor/importers/common/track_tracker.h"
29 #include "src/trace_processor/importers/common/tracks.h"
30 #include "src/trace_processor/importers/ftrace/virtio_video_tracker.h"
31 #include "src/trace_processor/storage/trace_storage.h"
32 #include "src/trace_processor/types/variadic.h"
33
34 #include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
35 #include "protos/perfetto/trace/ftrace/virtio_video.pbzero.h"
36
37 namespace perfetto::trace_processor {
38
39 namespace {
40 using protos::pbzero::FtraceEvent;
41 using protos::pbzero::VirtioVideoCmdDoneFtraceEvent;
42 using protos::pbzero::VirtioVideoCmdFtraceEvent;
43 using protos::pbzero::VirtioVideoResourceQueueDoneFtraceEvent;
44 using protos::pbzero::VirtioVideoResourceQueueFtraceEvent;
45 using protozero::ConstBytes;
46
47 /* VIRTIO_VIDEO_QUEUE_TYPE_INPUT */
48 constexpr uint64_t kVirtioVideoQueueTypeInput = 0x100;
49
50 /* VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT */
51 constexpr uint64_t kVirtioVideoQueueTypeOutput = 0x101;
52
53 constexpr int64_t kVirtioVideoCmdDuration = 100000;
54
NameForQueueType(uint32_t queue_type)55 const char* NameForQueueType(uint32_t queue_type) {
56 switch (queue_type) {
57 case kVirtioVideoQueueTypeInput:
58 return "INPUT";
59 case kVirtioVideoQueueTypeOutput:
60 return "OUTPUT";
61 default:
62 return "Unknown";
63 }
64 PERFETTO_FATAL("For GCC");
65 }
66
67 constexpr auto kQueueEventBlueprint = TrackCompressor::SliceBlueprint(
68 "virtio_video_queue_event",
69 tracks::Dimensions(tracks::UintDimensionBlueprint("virtio_stream_id"),
70 tracks::UintDimensionBlueprint("virtio_queue_type")),
__anonafaa8efd0202(uint32_t stream_id, uint32_t queue_type) 71 tracks::FnNameBlueprint([](uint32_t stream_id, uint32_t queue_type) {
72 return base::StackString<255>("virtio_video stream #%" PRIu32 " %s",
73 stream_id, NameForQueueType(queue_type));
74 }));
75
76 constexpr auto kCommandBlueprint = TrackCompressor::SliceBlueprint(
77 "virtio_video_command",
78 tracks::Dimensions(tracks::UintDimensionBlueprint("virtio_stream_id"),
79 tracks::UintDimensionBlueprint("is_response")),
__anonafaa8efd0302(uint32_t stream_id, uint32_t is_response) 80 tracks::FnNameBlueprint([](uint32_t stream_id, uint32_t is_response) {
81 const char* suffix = is_response ? "Responses" : "Requests";
82 return base::StackString<64>("virtio_video stream #%u %s", stream_id,
83 suffix);
84 }));
85
86 } // namespace
87
VirtioVideoTracker(TraceProcessorContext * context)88 VirtioVideoTracker::VirtioVideoTracker(TraceProcessorContext* context)
89 : context_(context),
90 unknown_id_(context->storage->InternString("Unknown")),
91 input_queue_id_(context->storage->InternString("INPUT")),
92 output_queue_id_(context->storage->InternString("OUTPUT")),
93 fields_string_ids_(*context->storage) {
94 TraceStorage& storage = *context_->storage;
95
96 command_names_.Insert(0x100, storage.InternString("QUERY_CAPABILITY"));
97 command_names_.Insert(0x101, storage.InternString("STREAM_CREATE"));
98 command_names_.Insert(0x102, storage.InternString("STREAM_DESTROY"));
99 command_names_.Insert(0x103, storage.InternString("STREAM_DRAIN"));
100 command_names_.Insert(0x104, storage.InternString("RESOURCE_CREATE"));
101 command_names_.Insert(0x105, storage.InternString("RESOURCE_QUEUE"));
102 command_names_.Insert(0x106, storage.InternString("RESOURCE_DESTROY_ALL"));
103 command_names_.Insert(0x107, storage.InternString("QUEUE_CLEAR"));
104 command_names_.Insert(0x108, storage.InternString("GET_PARAMS"));
105 command_names_.Insert(0x109, storage.InternString("SET_PARAMS"));
106 command_names_.Insert(0x10a, storage.InternString("QUERY_CONTROL"));
107 command_names_.Insert(0x10b, storage.InternString("GET_CONTROL"));
108 command_names_.Insert(0x10c, storage.InternString("SET_CONTROL"));
109 command_names_.Insert(0x10d, storage.InternString("GET_PARAMS_EXT"));
110 command_names_.Insert(0x10e, storage.InternString("SET_PARAMS_EXT"));
111 }
112
113 VirtioVideoTracker::~VirtioVideoTracker() = default;
114
ParseVirtioVideoEvent(uint64_t fld_id,int64_t timestamp,const ConstBytes & blob)115 void VirtioVideoTracker::ParseVirtioVideoEvent(uint64_t fld_id,
116 int64_t timestamp,
117 const ConstBytes& blob) {
118 switch (fld_id) {
119 case FtraceEvent::kVirtioVideoResourceQueueFieldNumber: {
120 VirtioVideoResourceQueueFtraceEvent::Decoder pb_evt(blob);
121
122 base::StackString<64> name("Resource #%d", pb_evt.resource_id());
123 StringId name_id = context_->storage->InternString(name.string_view());
124
125 TrackId begin_id = context_->track_compressor->InternBegin(
126 kQueueEventBlueprint,
127 tracks::Dimensions(pb_evt.stream_id(), pb_evt.queue_type()),
128 static_cast<int64_t>(pb_evt.resource_id()));
129 context_->slice_tracker->Begin(timestamp, begin_id, kNullStringId,
130 name_id);
131 break;
132 }
133 case FtraceEvent::kVirtioVideoResourceQueueDoneFieldNumber: {
134 VirtioVideoResourceQueueDoneFtraceEvent::Decoder pb_evt(blob);
135
136 TrackId end_id = context_->track_compressor->InternEnd(
137 kQueueEventBlueprint,
138 tracks::Dimensions(pb_evt.stream_id(), pb_evt.queue_type()),
139 static_cast<int64_t>(pb_evt.resource_id()));
140 context_->slice_tracker->End(
141 timestamp, end_id, {}, {},
142 [this, &pb_evt](ArgsTracker::BoundInserter* args) {
143 this->AddCommandSliceArgs(&pb_evt, args);
144 });
145 break;
146 }
147 case FtraceEvent::kVirtioVideoCmdFieldNumber: {
148 VirtioVideoCmdFtraceEvent::Decoder pb_evt(blob);
149 AddCommandSlice(timestamp, pb_evt.stream_id(), pb_evt.type(), false);
150 break;
151 }
152 case FtraceEvent::kVirtioVideoCmdDoneFieldNumber: {
153 VirtioVideoCmdDoneFtraceEvent::Decoder pb_evt(blob);
154 AddCommandSlice(timestamp, pb_evt.stream_id(), pb_evt.type(), true);
155 break;
156 }
157 }
158 }
159
FieldsStringIds(TraceStorage & storage)160 VirtioVideoTracker::FieldsStringIds::FieldsStringIds(TraceStorage& storage)
161 : stream_id(storage.InternString("stream_id")),
162 resource_id(storage.InternString("resource_id")),
163 queue_type(storage.InternString("queue_type")),
164 data_size0(storage.InternString("data_size0")),
165 data_size1(storage.InternString("data_size1")),
166 data_size2(storage.InternString("data_size2")),
167 data_size3(storage.InternString("data_size3")),
168 timestamp(storage.InternString("timestamp")) {}
169
AddCommandSlice(int64_t timestamp,uint32_t stream_id,uint64_t type,bool response)170 void VirtioVideoTracker::AddCommandSlice(int64_t timestamp,
171 uint32_t stream_id,
172 uint64_t type,
173 bool response) {
174 const StringId* cmd_name_id = command_names_.Find(type);
175 if (!cmd_name_id) {
176 cmd_name_id = &unknown_id_;
177 }
178
179 TrackId track_id = context_->track_compressor->InternScoped(
180 kCommandBlueprint, tracks::Dimensions(stream_id, response), timestamp,
181 kVirtioVideoCmdDuration);
182 context_->slice_tracker->Scoped(timestamp, track_id, kNullStringId,
183 *cmd_name_id, kVirtioVideoCmdDuration);
184 }
185
AddCommandSliceArgs(protos::pbzero::VirtioVideoResourceQueueDoneFtraceEvent::Decoder * pb_evt,ArgsTracker::BoundInserter * args)186 void VirtioVideoTracker::AddCommandSliceArgs(
187 protos::pbzero::VirtioVideoResourceQueueDoneFtraceEvent::Decoder* pb_evt,
188 ArgsTracker::BoundInserter* args) {
189 StringId queue_type_id;
190 switch (pb_evt->queue_type()) {
191 case kVirtioVideoQueueTypeInput: {
192 queue_type_id = input_queue_id_;
193 break;
194 }
195 case kVirtioVideoQueueTypeOutput: {
196 queue_type_id = output_queue_id_;
197 break;
198 }
199 default: {
200 queue_type_id = unknown_id_;
201 break;
202 }
203 }
204
205 args->AddArg(fields_string_ids_.stream_id,
206 Variadic::Integer(pb_evt->stream_id()));
207 args->AddArg(fields_string_ids_.resource_id,
208 Variadic::Integer(pb_evt->resource_id()));
209 args->AddArg(fields_string_ids_.queue_type, Variadic::String(queue_type_id));
210 args->AddArg(fields_string_ids_.data_size0,
211 Variadic::Integer(pb_evt->data_size0()));
212 args->AddArg(fields_string_ids_.data_size1,
213 Variadic::Integer(pb_evt->data_size1()));
214 args->AddArg(fields_string_ids_.data_size2,
215 Variadic::Integer(pb_evt->data_size2()));
216 args->AddArg(fields_string_ids_.data_size3,
217 Variadic::Integer(pb_evt->data_size3()));
218 args->AddArg(fields_string_ids_.timestamp,
219 Variadic::UnsignedInteger(pb_evt->timestamp()));
220 }
221
222 } // namespace perfetto::trace_processor
223