• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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/ftrace/ftrace_parser.h"
18 
19 #include "perfetto/base/logging.h"
20 #include "perfetto/ext/base/string_utils.h"
21 #include "perfetto/ext/base/string_writer.h"
22 #include "perfetto/protozero/proto_decoder.h"
23 #include "src/trace_processor/importers/common/args_tracker.h"
24 #include "src/trace_processor/importers/common/async_track_set_tracker.h"
25 #include "src/trace_processor/importers/common/metadata_tracker.h"
26 #include "src/trace_processor/importers/common/parser_types.h"
27 #include "src/trace_processor/importers/common/process_tracker.h"
28 #include "src/trace_processor/importers/common/track_tracker.h"
29 #include "src/trace_processor/importers/ftrace/binder_tracker.h"
30 #include "src/trace_processor/importers/ftrace/thread_state_tracker.h"
31 #include "src/trace_processor/importers/ftrace/v4l2_tracker.h"
32 #include "src/trace_processor/importers/ftrace/virtio_video_tracker.h"
33 #include "src/trace_processor/importers/i2c/i2c_tracker.h"
34 #include "src/trace_processor/importers/proto/packet_sequence_state.h"
35 #include "src/trace_processor/importers/syscalls/syscall_tracker.h"
36 #include "src/trace_processor/importers/systrace/systrace_parser.h"
37 #include "src/trace_processor/storage/stats.h"
38 #include "src/trace_processor/storage/trace_storage.h"
39 #include "src/trace_processor/types/softirq_action.h"
40 #include "src/trace_processor/types/tcp_state.h"
41 
42 #include "protos/perfetto/common/gpu_counter_descriptor.pbzero.h"
43 #include "protos/perfetto/trace/ftrace/binder.pbzero.h"
44 #include "protos/perfetto/trace/ftrace/cma.pbzero.h"
45 #include "protos/perfetto/trace/ftrace/cpuhp.pbzero.h"
46 #include "protos/perfetto/trace/ftrace/cros_ec.pbzero.h"
47 #include "protos/perfetto/trace/ftrace/dmabuf_heap.pbzero.h"
48 #include "protos/perfetto/trace/ftrace/dpu.pbzero.h"
49 #include "protos/perfetto/trace/ftrace/fastrpc.pbzero.h"
50 #include "protos/perfetto/trace/ftrace/ftrace.pbzero.h"
51 #include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
52 #include "protos/perfetto/trace/ftrace/ftrace_stats.pbzero.h"
53 #include "protos/perfetto/trace/ftrace/g2d.pbzero.h"
54 #include "protos/perfetto/trace/ftrace/generic.pbzero.h"
55 #include "protos/perfetto/trace/ftrace/gpu_mem.pbzero.h"
56 #include "protos/perfetto/trace/ftrace/i2c.pbzero.h"
57 #include "protos/perfetto/trace/ftrace/ion.pbzero.h"
58 #include "protos/perfetto/trace/ftrace/irq.pbzero.h"
59 #include "protos/perfetto/trace/ftrace/kmem.pbzero.h"
60 #include "protos/perfetto/trace/ftrace/lowmemorykiller.pbzero.h"
61 #include "protos/perfetto/trace/ftrace/lwis.pbzero.h"
62 #include "protos/perfetto/trace/ftrace/mali.pbzero.h"
63 #include "protos/perfetto/trace/ftrace/mm_event.pbzero.h"
64 #include "protos/perfetto/trace/ftrace/net.pbzero.h"
65 #include "protos/perfetto/trace/ftrace/oom.pbzero.h"
66 #include "protos/perfetto/trace/ftrace/power.pbzero.h"
67 #include "protos/perfetto/trace/ftrace/raw_syscalls.pbzero.h"
68 #include "protos/perfetto/trace/ftrace/sched.pbzero.h"
69 #include "protos/perfetto/trace/ftrace/scm.pbzero.h"
70 #include "protos/perfetto/trace/ftrace/sde.pbzero.h"
71 #include "protos/perfetto/trace/ftrace/signal.pbzero.h"
72 #include "protos/perfetto/trace/ftrace/skb.pbzero.h"
73 #include "protos/perfetto/trace/ftrace/sock.pbzero.h"
74 #include "protos/perfetto/trace/ftrace/synthetic.pbzero.h"
75 #include "protos/perfetto/trace/ftrace/systrace.pbzero.h"
76 #include "protos/perfetto/trace/ftrace/task.pbzero.h"
77 #include "protos/perfetto/trace/ftrace/tcp.pbzero.h"
78 #include "protos/perfetto/trace/ftrace/thermal.pbzero.h"
79 #include "protos/perfetto/trace/ftrace/trusty.pbzero.h"
80 #include "protos/perfetto/trace/ftrace/ufs.pbzero.h"
81 #include "protos/perfetto/trace/ftrace/vmscan.pbzero.h"
82 #include "protos/perfetto/trace/ftrace/workqueue.pbzero.h"
83 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
84 
85 namespace perfetto {
86 namespace trace_processor {
87 
88 namespace {
89 
90 using protozero::ConstBytes;
91 using protozero::ProtoDecoder;
92 
93 struct FtraceEventAndFieldId {
94   uint32_t event_id;
95   uint32_t field_id;
96 };
97 
98 // Contains a list of all the proto fields in ftrace events which represent
99 // kernel functions. This list is used to convert the iids in these fields to
100 // proper kernel symbols.
101 // TODO(lalitm): going through this array is O(n) on a hot-path (see
102 // ParseTypedFtraceToRaw). Consider changing this if we end up adding a lot of
103 // events here.
104 constexpr auto kKernelFunctionFields = std::array<FtraceEventAndFieldId, 6>{
105     FtraceEventAndFieldId{
106         protos::pbzero::FtraceEvent::kSchedBlockedReasonFieldNumber,
107         protos::pbzero::SchedBlockedReasonFtraceEvent::kCallerFieldNumber},
108     FtraceEventAndFieldId{
109         protos::pbzero::FtraceEvent::kWorkqueueExecuteStartFieldNumber,
110         protos::pbzero::WorkqueueExecuteStartFtraceEvent::kFunctionFieldNumber},
111     FtraceEventAndFieldId{
112         protos::pbzero::FtraceEvent::kWorkqueueQueueWorkFieldNumber,
113         protos::pbzero::WorkqueueQueueWorkFtraceEvent::kFunctionFieldNumber},
114     FtraceEventAndFieldId{
115         protos::pbzero::FtraceEvent::kFuncgraphEntryFieldNumber,
116         protos::pbzero::FuncgraphEntryFtraceEvent::kFuncFieldNumber},
117     FtraceEventAndFieldId{
118         protos::pbzero::FtraceEvent::kFuncgraphExitFieldNumber,
119         protos::pbzero::FuncgraphExitFtraceEvent::kFuncFieldNumber},
120     FtraceEventAndFieldId{
121         protos::pbzero::FtraceEvent::kMmShrinkSlabStartFieldNumber,
122         protos::pbzero::MmShrinkSlabStartFtraceEvent::kShrinkFieldNumber}};
123 
GetUfsCmdString(uint32_t ufsopcode,uint32_t gid)124 std::string GetUfsCmdString(uint32_t ufsopcode, uint32_t gid) {
125   std::string buffer;
126   switch (ufsopcode) {
127     case 4:
128       buffer = "FORMAT UNIT";
129       break;
130     case 18:
131       buffer = "INQUIRY";
132       break;
133     case 85:
134       buffer = "MODE SELECT (10)";
135       break;
136     case 90:
137       buffer = "MODE SENSE (10)";
138       break;
139     case 52:
140       buffer = "PRE-FETCH (10)";
141       break;
142     case 144:
143       buffer = "PRE-FETCH (16)";
144       break;
145     case 8:
146       buffer = "READ (6)";
147       break;
148     case 40:
149       buffer = "READ (10)";
150       break;
151     case 136:
152       buffer = "READ (16)";
153       break;
154     case 60:
155       buffer = "READ BUFFER";
156       break;
157     case 37:
158       buffer = "READ CAPACITY (10)";
159       break;
160     case 158:
161       buffer = "READ CAPACITY (16)";
162       break;
163     case 160:
164       buffer = "REPORT LUNS";
165       break;
166     case 3:
167       buffer = "REQUEST SENSE";
168       break;
169     case 162:
170       buffer = "SECURITY PROTOCOL IN";
171       break;
172     case 181:
173       buffer = "SECURITY PROTOCOL OUT";
174       break;
175     case 29:
176       buffer = "SEND DIAGNOSTIC";
177       break;
178     case 27:
179       buffer = "START STOP UNIT";
180       break;
181     case 53:
182       buffer = "SYNCHRONIZE CACHE (10)";
183       break;
184     case 145:
185       buffer = "SYNCHRONIZE CACHE (16)";
186       break;
187     case 0:
188       buffer = "TEST UNIT READY";
189       break;
190     case 66:
191       buffer = "UNMAP";
192       break;
193     case 47:
194       buffer = "VERIFY";
195       break;
196     case 10:
197       buffer = "WRITE (6)";
198       break;
199     case 42:
200       buffer = "WRITE (10)";
201       break;
202     case 138:
203       buffer = "WRITE (16)";
204       break;
205     case 59:
206       buffer = "WRITE BUFFER";
207       break;
208     default:
209       buffer = "UNDEFINED";
210       break;
211   }
212   if (gid > 0) {
213     base::StackString<32> gid_str(" (GID=0x%x)", gid);
214     buffer = buffer + gid_str.c_str();
215   }
216   return buffer;
217 }
218 }  // namespace
219 
FtraceParser(TraceProcessorContext * context)220 FtraceParser::FtraceParser(TraceProcessorContext* context)
221     : context_(context),
222       rss_stat_tracker_(context),
223       drm_tracker_(context),
224       iostat_tracker_(context),
225       virtio_gpu_tracker_(context),
226       mali_gpu_event_tracker_(context),
227       pkvm_hyp_cpu_tracker_(context),
228       sched_wakeup_name_id_(context->storage->InternString("sched_wakeup")),
229       sched_waking_name_id_(context->storage->InternString("sched_waking")),
230       cpu_id_(context->storage->InternString("cpu")),
231       cpu_freq_name_id_(context->storage->InternString("cpufreq")),
232       gpu_freq_name_id_(context->storage->InternString("gpufreq")),
233       cpu_idle_name_id_(context->storage->InternString("cpuidle")),
234       suspend_resume_name_id_(
235           context->storage->InternString("Suspend/Resume Latency")),
236       suspend_resume_minimal_name_id_(
237           context->storage->InternString("Suspend/Resume Minimal")),
238       suspend_resume_minimal_slice_name_id_(
239           context->storage->InternString("Suspended")),
240       kfree_skb_name_id_(context->storage->InternString("Kfree Skb IP Prot")),
241       ion_total_id_(context->storage->InternString("mem.ion")),
242       ion_change_id_(context->storage->InternString("mem.ion_change")),
243       ion_buffer_id_(context->storage->InternString("mem.ion_buffer")),
244       dma_heap_total_id_(context->storage->InternString("mem.dma_heap")),
245       dma_heap_change_id_(
246           context->storage->InternString("mem.dma_heap_change")),
247       dma_buffer_id_(context->storage->InternString("mem.dma_buffer")),
248       ion_total_unknown_id_(context->storage->InternString("mem.ion.unknown")),
249       ion_change_unknown_id_(
250           context->storage->InternString("mem.ion_change.unknown")),
251       signal_generate_id_(context->storage->InternString("signal_generate")),
252       signal_deliver_id_(context->storage->InternString("signal_deliver")),
253       oom_score_adj_id_(context->storage->InternString("oom_score_adj")),
254       lmk_id_(context->storage->InternString("mem.lmk")),
255       comm_name_id_(context->storage->InternString("comm")),
256       signal_name_id_(context_->storage->InternString("signal.sig")),
257       oom_kill_id_(context_->storage->InternString("mem.oom_kill")),
258       workqueue_id_(context_->storage->InternString("workqueue")),
259       irq_id_(context_->storage->InternString("irq")),
260       tcp_state_id_(context_->storage->InternString("tcp_state")),
261       tcp_event_id_(context_->storage->InternString("tcp_event")),
262       protocol_arg_id_(context_->storage->InternString("protocol")),
263       napi_gro_id_(context_->storage->InternString("napi_gro")),
264       tcp_retransmited_name_id_(
265           context_->storage->InternString("TCP Retransmit Skb")),
266       ret_arg_id_(context_->storage->InternString("ret")),
267       len_arg_id_(context->storage->InternString("len")),
268       direct_reclaim_nr_reclaimed_id_(
269           context->storage->InternString("direct_reclaim_nr_reclaimed")),
270       direct_reclaim_order_id_(
271           context->storage->InternString("direct_reclaim_order")),
272       direct_reclaim_may_writepage_id_(
273           context->storage->InternString("direct_reclaim_may_writepage")),
274       direct_reclaim_gfp_flags_id_(
275           context->storage->InternString("direct_reclaim_gfp_flags")),
276       vec_arg_id_(context->storage->InternString("vec")),
277       gpu_mem_total_name_id_(context->storage->InternString("GPU Memory")),
278       gpu_mem_total_unit_id_(context->storage->InternString(
279           std::to_string(protos::pbzero::GpuCounterDescriptor::BYTE).c_str())),
280       gpu_mem_total_global_desc_id_(context->storage->InternString(
281           "Total GPU memory used by the entire system")),
282       gpu_mem_total_proc_desc_id_(context->storage->InternString(
283           "Total GPU memory used by this process")),
284       io_wait_id_(context->storage->InternString("io_wait")),
285       function_id_(context->storage->InternString("function")),
286       waker_utid_id_(context->storage->InternString("waker_utid")),
287       cros_ec_arg_num_id_(context->storage->InternString("ec_num")),
288       cros_ec_arg_ec_id_(context->storage->InternString("ec_delta")),
289       cros_ec_arg_sample_ts_id_(context->storage->InternString("sample_ts")),
290       ufs_clkgating_id_(context->storage->InternString(
291           "io.ufs.clkgating (OFF:0/REQ_OFF/REQ_ON/ON:3)")),
292       ufs_command_count_id_(
293           context->storage->InternString("io.ufs.command.count")),
294       shrink_slab_id_(context_->storage->InternString("mm_vmscan_shrink_slab")),
295       shrink_name_id_(context->storage->InternString("shrink_name")),
296       shrink_total_scan_id_(context->storage->InternString("total_scan")),
297       shrink_freed_id_(context->storage->InternString("freed")),
298       shrink_priority_id_(context->storage->InternString("priority")),
299       trusty_category_id_(context_->storage->InternString("tipc")),
300       trusty_name_trusty_std_id_(context_->storage->InternString("trusty_std")),
301       trusty_name_tipc_rx_id_(context_->storage->InternString("tipc_rx")),
302       cma_alloc_id_(context_->storage->InternString("mm_cma_alloc")),
303       cma_name_id_(context_->storage->InternString("cma_name")),
304       cma_pfn_id_(context_->storage->InternString("cma_pfn")),
305       cma_req_pages_id_(context_->storage->InternString("cma_req_pages")),
306       cma_nr_migrated_id_(context_->storage->InternString("cma_nr_migrated")),
307       cma_nr_reclaimed_id_(context_->storage->InternString("cma_nr_reclaimed")),
308       cma_nr_mapped_id_(context_->storage->InternString("cma_nr_mapped")),
309       cma_nr_isolate_fail_id_(
310           context_->storage->InternString("cma_nr_isolate_fail")),
311       cma_nr_migrate_fail_id_(
312           context_->storage->InternString("cma_nr_migrate_fail")),
313       cma_nr_test_fail_id_(context_->storage->InternString("cma_nr_test_fail")),
314       syscall_ret_id_(context->storage->InternString("ret")),
315       syscall_args_id_(context->storage->InternString("args")),
316       replica_slice_id_(context->storage->InternString("replica_slice")) {
317   // Build the lookup table for the strings inside ftrace events (e.g. the
318   // name of ftrace event fields and the names of their args).
319   for (size_t i = 0; i < GetDescriptorsSize(); i++) {
320     auto* descriptor = GetMessageDescriptorForId(i);
321     if (!descriptor->name) {
322       ftrace_message_strings_.emplace_back();
323       continue;
324     }
325 
326     FtraceMessageStrings ftrace_strings;
327     ftrace_strings.message_name_id =
328         context->storage->InternString(descriptor->name);
329 
330     for (size_t fid = 0; fid <= descriptor->max_field_id; fid++) {
331       const auto& field = descriptor->fields[fid];
332       if (!field.name)
333         continue;
334       ftrace_strings.field_name_ids[fid] =
335           context->storage->InternString(field.name);
336     }
337     ftrace_message_strings_.emplace_back(ftrace_strings);
338   }
339 
340   // Array initialization causes a spurious warning due to llvm bug.
341   // See https://bugs.llvm.org/show_bug.cgi?id=21629
342   fast_rpc_delta_names_[0] =
343       context->storage->InternString("mem.fastrpc_change[ASDP]");
344   fast_rpc_delta_names_[1] =
345       context->storage->InternString("mem.fastrpc_change[MDSP]");
346   fast_rpc_delta_names_[2] =
347       context->storage->InternString("mem.fastrpc_change[SDSP]");
348   fast_rpc_delta_names_[3] =
349       context->storage->InternString("mem.fastrpc_change[CDSP]");
350   fast_rpc_total_names_[0] =
351       context->storage->InternString("mem.fastrpc[ASDP]");
352   fast_rpc_total_names_[1] =
353       context->storage->InternString("mem.fastrpc[MDSP]");
354   fast_rpc_total_names_[2] =
355       context->storage->InternString("mem.fastrpc[SDSP]");
356   fast_rpc_total_names_[3] =
357       context->storage->InternString("mem.fastrpc[CDSP]");
358 
359   mm_event_counter_names_ = {
360       {MmEventCounterNames(
361            context->storage->InternString("mem.mm.min_flt.count"),
362            context->storage->InternString("mem.mm.min_flt.max_lat"),
363            context->storage->InternString("mem.mm.min_flt.avg_lat")),
364        MmEventCounterNames(
365            context->storage->InternString("mem.mm.maj_flt.count"),
366            context->storage->InternString("mem.mm.maj_flt.max_lat"),
367            context->storage->InternString("mem.mm.maj_flt.avg_lat")),
368        MmEventCounterNames(
369            context->storage->InternString("mem.mm.read_io.count"),
370            context->storage->InternString("mem.mm.read_io.max_lat"),
371            context->storage->InternString("mem.mm.read_io.avg_lat")),
372        MmEventCounterNames(
373            context->storage->InternString("mem.mm.compaction.count"),
374            context->storage->InternString("mem.mm.compaction.max_lat"),
375            context->storage->InternString("mem.mm.compaction.avg_lat")),
376        MmEventCounterNames(
377            context->storage->InternString("mem.mm.reclaim.count"),
378            context->storage->InternString("mem.mm.reclaim.max_lat"),
379            context->storage->InternString("mem.mm.reclaim.avg_lat")),
380        MmEventCounterNames(
381            context->storage->InternString("mem.mm.swp_flt.count"),
382            context->storage->InternString("mem.mm.swp_flt.max_lat"),
383            context->storage->InternString("mem.mm.swp_flt.avg_lat")),
384        MmEventCounterNames(
385            context->storage->InternString("mem.mm.kern_alloc.count"),
386            context->storage->InternString("mem.mm.kern_alloc.max_lat"),
387            context->storage->InternString("mem.mm.kern_alloc.avg_lat"))}};
388 }
389 
ParseFtraceStats(ConstBytes blob,uint32_t packet_sequence_id)390 void FtraceParser::ParseFtraceStats(ConstBytes blob,
391                                     uint32_t packet_sequence_id) {
392   protos::pbzero::FtraceStats::Decoder evt(blob.data, blob.size);
393   bool is_start =
394       evt.phase() == protos::pbzero::FtraceStats::Phase::START_OF_TRACE;
395   bool is_end = evt.phase() == protos::pbzero::FtraceStats::Phase::END_OF_TRACE;
396   if (!is_start && !is_end) {
397     PERFETTO_ELOG("Ignoring unknown ftrace stats phase %d", evt.phase());
398     return;
399   }
400   size_t phase = is_end ? 1 : 0;
401 
402   // This code relies on the fact that each ftrace_cpu_XXX_end event is
403   // just after the corresponding ftrace_cpu_XXX_begin event.
404   static_assert(
405       stats::ftrace_cpu_read_events_end - stats::ftrace_cpu_read_events_begin ==
406               1 &&
407           stats::ftrace_cpu_entries_end - stats::ftrace_cpu_entries_begin == 1,
408       "ftrace_cpu_XXX stats definition are messed up");
409 
410   auto* storage = context_->storage.get();
411   for (auto it = evt.cpu_stats(); it; ++it) {
412     protos::pbzero::FtraceCpuStats::Decoder cpu_stats(*it);
413     int cpu = static_cast<int>(cpu_stats.cpu());
414 
415     int64_t entries = static_cast<int64_t>(cpu_stats.entries());
416     int64_t overrun = static_cast<int64_t>(cpu_stats.overrun());
417     int64_t commit_overrun = static_cast<int64_t>(cpu_stats.commit_overrun());
418     int64_t bytes_read = static_cast<int64_t>(cpu_stats.bytes_read());
419     int64_t dropped_events = static_cast<int64_t>(cpu_stats.dropped_events());
420     int64_t read_events = static_cast<int64_t>(cpu_stats.read_events());
421     int64_t now_ts = static_cast<int64_t>(cpu_stats.now_ts() * 1e9);
422 
423     storage->SetIndexedStats(stats::ftrace_cpu_entries_begin + phase, cpu,
424                              entries);
425     storage->SetIndexedStats(stats::ftrace_cpu_overrun_begin + phase, cpu,
426                              overrun);
427     storage->SetIndexedStats(stats::ftrace_cpu_commit_overrun_begin + phase,
428                              cpu, commit_overrun);
429     storage->SetIndexedStats(stats::ftrace_cpu_bytes_read_begin + phase, cpu,
430                              bytes_read);
431     storage->SetIndexedStats(stats::ftrace_cpu_dropped_events_begin + phase,
432                              cpu, dropped_events);
433     storage->SetIndexedStats(stats::ftrace_cpu_read_events_begin + phase, cpu,
434                              read_events);
435     storage->SetIndexedStats(stats::ftrace_cpu_now_ts_begin + phase, cpu,
436                              now_ts);
437 
438     if (is_end) {
439       auto opt_entries_begin =
440           storage->GetIndexedStats(stats::ftrace_cpu_entries_begin, cpu);
441       if (opt_entries_begin) {
442         int64_t delta_entries = entries - opt_entries_begin.value();
443         storage->SetIndexedStats(stats::ftrace_cpu_entries_delta, cpu,
444                                  delta_entries);
445       }
446 
447       auto opt_overrun_begin =
448           storage->GetIndexedStats(stats::ftrace_cpu_overrun_begin, cpu);
449       if (opt_overrun_begin) {
450         int64_t delta_overrun = overrun - opt_overrun_begin.value();
451         storage->SetIndexedStats(stats::ftrace_cpu_overrun_delta, cpu,
452                                  delta_overrun);
453       }
454 
455       auto opt_commit_overrun_begin =
456           storage->GetIndexedStats(stats::ftrace_cpu_commit_overrun_begin, cpu);
457       if (opt_commit_overrun_begin) {
458         int64_t delta_commit_overrun =
459             commit_overrun - opt_commit_overrun_begin.value();
460         storage->SetIndexedStats(stats::ftrace_cpu_commit_overrun_delta, cpu,
461                                  delta_commit_overrun);
462       }
463 
464       auto opt_bytes_read_begin =
465           storage->GetIndexedStats(stats::ftrace_cpu_bytes_read_begin, cpu);
466       if (opt_bytes_read_begin) {
467         int64_t delta_bytes_read = bytes_read - opt_bytes_read_begin.value();
468         storage->SetIndexedStats(stats::ftrace_cpu_bytes_read_delta, cpu,
469                                  delta_bytes_read);
470       }
471 
472       auto opt_dropped_events_begin =
473           storage->GetIndexedStats(stats::ftrace_cpu_dropped_events_begin, cpu);
474       if (opt_dropped_events_begin) {
475         int64_t delta_dropped_events =
476             dropped_events - opt_dropped_events_begin.value();
477         storage->SetIndexedStats(stats::ftrace_cpu_dropped_events_delta, cpu,
478                                  delta_dropped_events);
479       }
480 
481       auto opt_read_events_begin =
482           storage->GetIndexedStats(stats::ftrace_cpu_read_events_begin, cpu);
483       if (opt_read_events_begin) {
484         int64_t delta_read_events = read_events - opt_read_events_begin.value();
485         storage->SetIndexedStats(stats::ftrace_cpu_read_events_delta, cpu,
486                                  delta_read_events);
487       }
488     }
489 
490     // oldest_event_ts can often be set to very high values, possibly because
491     // of wrapping. Ensure that we are not overflowing to avoid ubsan
492     // complaining.
493     double oldest_event_ts = cpu_stats.oldest_event_ts() * 1e9;
494     // NB: This comparison is correct only because of the >=, it would be
495     // incorrect with >. std::numeric_limits<int64_t>::max() converted to
496     // a double is the next value representable as a double that is *larger*
497     // than std::numeric_limits<int64_t>::max(). All values that are
498     // representable as doubles and < than that value are thus representable
499     // as int64_t.
500     if (oldest_event_ts >=
501         static_cast<double>(std::numeric_limits<int64_t>::max())) {
502       storage->SetIndexedStats(stats::ftrace_cpu_oldest_event_ts_begin + phase,
503                                cpu, std::numeric_limits<int64_t>::max());
504     } else {
505       storage->SetIndexedStats(stats::ftrace_cpu_oldest_event_ts_begin + phase,
506                                cpu, static_cast<int64_t>(oldest_event_ts));
507     }
508   }
509 
510   // Compute atrace + ftrace setup errors. We do two things here:
511   // 1. We add up all the errors and put the counter in the stats table (which
512   //    can hold only numerals).
513   // 2. We concatenate together all the errors in a string and put that in the
514   //    medatata table.
515   // Both will be reported in the 'Info & stats' page in the UI.
516   if (is_start) {
517     if (seen_errors_for_sequence_id_.count(packet_sequence_id) == 0) {
518       std::string error_str;
519       for (auto it = evt.failed_ftrace_events(); it; ++it) {
520         storage->IncrementStats(stats::ftrace_setup_errors, 1);
521         error_str += "Ftrace event failed: " + it->as_std_string() + "\n";
522       }
523       for (auto it = evt.unknown_ftrace_events(); it; ++it) {
524         storage->IncrementStats(stats::ftrace_setup_errors, 1);
525         error_str += "Ftrace event unknown: " + it->as_std_string() + "\n";
526       }
527       if (evt.atrace_errors().size > 0) {
528         storage->IncrementStats(stats::ftrace_setup_errors, 1);
529         error_str += "Atrace failures: " + evt.atrace_errors().ToStdString();
530       }
531       if (!error_str.empty()) {
532         auto error_str_id = storage->InternString(base::StringView(error_str));
533         context_->metadata_tracker->AppendMetadata(
534             metadata::ftrace_setup_errors, Variadic::String(error_str_id));
535         seen_errors_for_sequence_id_.insert(packet_sequence_id);
536       }
537     }
538     if (evt.preserve_ftrace_buffer()) {
539       preserve_ftrace_buffer_ = true;
540     }
541   }
542 }
543 
ParseFtraceEvent(uint32_t cpu,int64_t ts,const TracePacketData & data)544 util::Status FtraceParser::ParseFtraceEvent(uint32_t cpu,
545                                             int64_t ts,
546                                             const TracePacketData& data) {
547   MaybeOnFirstFtraceEvent();
548   if (PERFETTO_UNLIKELY(ts < drop_ftrace_data_before_ts_)) {
549     context_->storage->IncrementStats(
550         stats::ftrace_packet_before_tracing_start);
551     return util::OkStatus();
552   }
553   using protos::pbzero::FtraceEvent;
554   const TraceBlobView& event = data.packet;
555   PacketSequenceStateGeneration* seq_state = data.sequence_state.get();
556   ProtoDecoder decoder(event.data(), event.length());
557   uint64_t raw_pid = 0;
558   bool no_pid = false;
559   if (auto pid_field = decoder.FindField(FtraceEvent::kPidFieldNumber)) {
560     raw_pid = pid_field.as_uint64();
561   } else {
562     no_pid = true;
563   }
564   uint32_t pid = static_cast<uint32_t>(raw_pid);
565 
566   for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
567     bool is_metadata_field = fld.id() == FtraceEvent::kPidFieldNumber ||
568                              fld.id() == FtraceEvent::kTimestampFieldNumber;
569     if (is_metadata_field)
570       continue;
571 
572     // pKVM hypervisor events are recorded as ftrace events, however they are
573     // not associated with any pid. The rest of trace parsing logic for
574     // hypervisor events will use the pid 0.
575     if (no_pid && !PkvmHypervisorCpuTracker::IsPkvmHypervisorEvent(fld.id())) {
576       return util::ErrStatus("Pid field not found in ftrace packet");
577     }
578 
579     ConstBytes fld_bytes = fld.as_bytes();
580     if (fld.id() == FtraceEvent::kGenericFieldNumber) {
581       ParseGenericFtrace(ts, cpu, pid, fld_bytes);
582     } else if (fld.id() != FtraceEvent::kSchedSwitchFieldNumber) {
583       // sched_switch parsing populates the raw table by itself
584       ParseTypedFtraceToRaw(fld.id(), ts, cpu, pid, fld_bytes, seq_state);
585     }
586 
587     if (PkvmHypervisorCpuTracker::IsPkvmHypervisorEvent(fld.id())) {
588       pkvm_hyp_cpu_tracker_.ParseHypEvent(cpu, ts, fld.id(), fld_bytes);
589     }
590 
591     switch (fld.id()) {
592       case FtraceEvent::kSchedSwitchFieldNumber: {
593         ParseSchedSwitch(cpu, ts, fld_bytes);
594         break;
595       }
596       case FtraceEvent::kSchedWakingFieldNumber: {
597         ParseSchedWaking(ts, pid, fld_bytes);
598         break;
599       }
600       case FtraceEvent::kSchedProcessFreeFieldNumber: {
601         ParseSchedProcessFree(ts, fld_bytes);
602         break;
603       }
604       case FtraceEvent::kCpuFrequencyFieldNumber: {
605         ParseCpuFreq(ts, fld_bytes);
606         break;
607       }
608       case FtraceEvent::kGpuFrequencyFieldNumber: {
609         ParseGpuFreq(ts, fld_bytes);
610         break;
611       }
612       case FtraceEvent::kCpuIdleFieldNumber: {
613         ParseCpuIdle(ts, fld_bytes);
614         break;
615       }
616       case FtraceEvent::kPrintFieldNumber: {
617         ParsePrint(ts, pid, fld_bytes);
618         break;
619       }
620       case FtraceEvent::kZeroFieldNumber: {
621         ParseZero(ts, pid, fld_bytes);
622         break;
623       }
624       case FtraceEvent::kRssStatThrottledFieldNumber:
625       case FtraceEvent::kRssStatFieldNumber: {
626         rss_stat_tracker_.ParseRssStat(ts, fld.id(), pid, fld_bytes);
627         break;
628       }
629       case FtraceEvent::kIonHeapGrowFieldNumber: {
630         ParseIonHeapGrowOrShrink(ts, pid, fld_bytes, true);
631         break;
632       }
633       case FtraceEvent::kIonHeapShrinkFieldNumber: {
634         ParseIonHeapGrowOrShrink(ts, pid, fld_bytes, false);
635         break;
636       }
637       case FtraceEvent::kIonStatFieldNumber: {
638         ParseIonStat(ts, pid, fld_bytes);
639         break;
640       }
641       case FtraceEvent::kDmaHeapStatFieldNumber: {
642         ParseDmaHeapStat(ts, pid, fld_bytes);
643         break;
644       }
645       case FtraceEvent::kSignalGenerateFieldNumber: {
646         ParseSignalGenerate(ts, fld_bytes);
647         break;
648       }
649       case FtraceEvent::kSignalDeliverFieldNumber: {
650         ParseSignalDeliver(ts, pid, fld_bytes);
651         break;
652       }
653       case FtraceEvent::kOomScoreAdjUpdateFieldNumber: {
654         ParseOOMScoreAdjUpdate(ts, fld_bytes);
655         break;
656       }
657       case FtraceEvent::kMarkVictimFieldNumber: {
658         ParseOOMKill(ts, fld_bytes);
659         break;
660       }
661       case FtraceEvent::kMmEventRecordFieldNumber: {
662         ParseMmEventRecord(ts, pid, fld_bytes);
663         break;
664       }
665       case FtraceEvent::kSysEnterFieldNumber: {
666         ParseSysEnterEvent(ts, pid, fld_bytes);
667         break;
668       }
669       case FtraceEvent::kSysExitFieldNumber: {
670         ParseSysExitEvent(ts, pid, fld_bytes);
671         break;
672       }
673       case FtraceEvent::kTaskNewtaskFieldNumber: {
674         ParseTaskNewTask(ts, pid, fld_bytes);
675         break;
676       }
677       case FtraceEvent::kTaskRenameFieldNumber: {
678         ParseTaskRename(fld_bytes);
679         break;
680       }
681       case FtraceEvent::kBinderTransactionFieldNumber: {
682         ParseBinderTransaction(ts, pid, fld_bytes);
683         break;
684       }
685       case FtraceEvent::kBinderTransactionReceivedFieldNumber: {
686         ParseBinderTransactionReceived(ts, pid, fld_bytes);
687         break;
688       }
689       case FtraceEvent::kBinderTransactionAllocBufFieldNumber: {
690         ParseBinderTransactionAllocBuf(ts, pid, fld_bytes);
691         break;
692       }
693       case FtraceEvent::kBinderLockFieldNumber: {
694         ParseBinderLock(ts, pid, fld_bytes);
695         break;
696       }
697       case FtraceEvent::kBinderUnlockFieldNumber: {
698         ParseBinderUnlock(ts, pid, fld_bytes);
699         break;
700       }
701       case FtraceEvent::kBinderLockedFieldNumber: {
702         ParseBinderLocked(ts, pid, fld_bytes);
703         break;
704       }
705       case FtraceEvent::kSdeTracingMarkWriteFieldNumber: {
706         ParseSdeTracingMarkWrite(ts, pid, fld_bytes);
707         break;
708       }
709       case FtraceEvent::kClockSetRateFieldNumber: {
710         ParseClockSetRate(ts, fld_bytes);
711         break;
712       }
713       case FtraceEvent::kClockEnableFieldNumber: {
714         ParseClockEnable(ts, fld_bytes);
715         break;
716       }
717       case FtraceEvent::kClockDisableFieldNumber: {
718         ParseClockDisable(ts, fld_bytes);
719         break;
720       }
721       case FtraceEvent::kScmCallStartFieldNumber: {
722         ParseScmCallStart(ts, pid, fld_bytes);
723         break;
724       }
725       case FtraceEvent::kScmCallEndFieldNumber: {
726         ParseScmCallEnd(ts, pid, fld_bytes);
727         break;
728       }
729       case FtraceEvent::kCmaAllocStartFieldNumber: {
730         ParseCmaAllocStart(ts, pid);
731         break;
732       }
733       case FtraceEvent::kCmaAllocInfoFieldNumber: {
734         ParseCmaAllocInfo(ts, pid, fld_bytes);
735         break;
736       }
737       case FtraceEvent::kMmVmscanDirectReclaimBeginFieldNumber: {
738         ParseDirectReclaimBegin(ts, pid, fld_bytes);
739         break;
740       }
741       case FtraceEvent::kMmVmscanDirectReclaimEndFieldNumber: {
742         ParseDirectReclaimEnd(ts, pid, fld_bytes);
743         break;
744       }
745       case FtraceEvent::kMmShrinkSlabStartFieldNumber: {
746         ParseShrinkSlabStart(ts, pid, fld_bytes, seq_state);
747         break;
748       }
749       case FtraceEvent::kMmShrinkSlabEndFieldNumber: {
750         ParseShrinkSlabEnd(ts, pid, fld_bytes);
751         break;
752       }
753       case FtraceEvent::kWorkqueueExecuteStartFieldNumber: {
754         ParseWorkqueueExecuteStart(cpu, ts, pid, fld_bytes, seq_state);
755         break;
756       }
757       case FtraceEvent::kWorkqueueExecuteEndFieldNumber: {
758         ParseWorkqueueExecuteEnd(ts, pid, fld_bytes);
759         break;
760       }
761       case FtraceEvent::kIrqHandlerEntryFieldNumber: {
762         ParseIrqHandlerEntry(cpu, ts, fld_bytes);
763         break;
764       }
765       case FtraceEvent::kIrqHandlerExitFieldNumber: {
766         ParseIrqHandlerExit(cpu, ts, fld_bytes);
767         break;
768       }
769       case FtraceEvent::kSoftirqEntryFieldNumber: {
770         ParseSoftIrqEntry(cpu, ts, fld_bytes);
771         break;
772       }
773       case FtraceEvent::kSoftirqExitFieldNumber: {
774         ParseSoftIrqExit(cpu, ts, fld_bytes);
775         break;
776       }
777       case FtraceEvent::kGpuMemTotalFieldNumber: {
778         ParseGpuMemTotal(ts, fld_bytes);
779         break;
780       }
781       case FtraceEvent::kThermalTemperatureFieldNumber: {
782         ParseThermalTemperature(ts, fld_bytes);
783         break;
784       }
785       case FtraceEvent::kCdevUpdateFieldNumber: {
786         ParseCdevUpdate(ts, fld_bytes);
787         break;
788       }
789       case FtraceEvent::kSchedBlockedReasonFieldNumber: {
790         ParseSchedBlockedReason(fld_bytes, seq_state);
791         break;
792       }
793       case FtraceEvent::kFastrpcDmaStatFieldNumber: {
794         ParseFastRpcDmaStat(ts, pid, fld_bytes);
795         break;
796       }
797       case FtraceEvent::kG2dTracingMarkWriteFieldNumber: {
798         ParseG2dTracingMarkWrite(ts, pid, fld_bytes);
799         break;
800       }
801       case FtraceEvent::kDpuTracingMarkWriteFieldNumber: {
802         ParseDpuTracingMarkWrite(ts, pid, fld_bytes);
803         break;
804       }
805       case FtraceEvent::kMaliTracingMarkWriteFieldNumber: {
806         ParseMaliTracingMarkWrite(ts, pid, fld_bytes);
807         break;
808       }
809       case FtraceEvent::kLwisTracingMarkWriteFieldNumber: {
810         ParseLwisTracingMarkWrite(ts, pid, fld_bytes);
811         break;
812       }
813       case FtraceEvent::kVirtioGpuCmdQueueFieldNumber:
814       case FtraceEvent::kVirtioGpuCmdResponseFieldNumber: {
815         virtio_gpu_tracker_.ParseVirtioGpu(ts, fld.id(), pid, fld_bytes);
816         break;
817       }
818       case FtraceEvent::kCpuhpPauseFieldNumber: {
819         ParseCpuhpPause(ts, pid, fld_bytes);
820         break;
821       }
822       case FtraceEvent::kNetifReceiveSkbFieldNumber: {
823         ParseNetifReceiveSkb(cpu, ts, fld_bytes);
824         break;
825       }
826       case FtraceEvent::kNetDevXmitFieldNumber: {
827         ParseNetDevXmit(cpu, ts, fld_bytes);
828         break;
829       }
830       case FtraceEvent::kInetSockSetStateFieldNumber: {
831         ParseInetSockSetState(ts, pid, fld_bytes);
832         break;
833       }
834       case FtraceEvent::kTcpRetransmitSkbFieldNumber: {
835         ParseTcpRetransmitSkb(ts, fld_bytes);
836         break;
837       }
838       case FtraceEvent::kNapiGroReceiveEntryFieldNumber: {
839         ParseNapiGroReceiveEntry(cpu, ts, fld_bytes);
840         break;
841       }
842       case FtraceEvent::kNapiGroReceiveExitFieldNumber: {
843         ParseNapiGroReceiveExit(cpu, ts, fld_bytes);
844         break;
845       }
846       case FtraceEvent::kCpuFrequencyLimitsFieldNumber: {
847         ParseCpuFrequencyLimits(ts, fld_bytes);
848         break;
849       }
850       case FtraceEvent::kKfreeSkbFieldNumber: {
851         ParseKfreeSkb(ts, fld_bytes);
852         break;
853       }
854       case FtraceEvent::kCrosEcSensorhubDataFieldNumber: {
855         ParseCrosEcSensorhubData(ts, fld_bytes);
856         break;
857       }
858       case FtraceEvent::kUfshcdCommandFieldNumber: {
859         ParseUfshcdCommand(ts, fld_bytes);
860         break;
861       }
862       case FtraceEvent::kWakeupSourceActivateFieldNumber: {
863         ParseWakeSourceActivate(ts, fld_bytes);
864         break;
865       }
866       case FtraceEvent::kWakeupSourceDeactivateFieldNumber: {
867         ParseWakeSourceDeactivate(ts, fld_bytes);
868         break;
869       }
870       case FtraceEvent::kUfshcdClkGatingFieldNumber: {
871         ParseUfshcdClkGating(ts, fld_bytes);
872         break;
873       }
874       case FtraceEvent::kSuspendResumeFieldNumber: {
875         ParseSuspendResume(ts, fld_bytes);
876         break;
877       }
878       case FtraceEvent::kSuspendResumeMinimalFieldNumber: {
879         ParseSuspendResumeMinimal(ts, fld_bytes);
880         break;
881       }
882       case FtraceEvent::kDrmVblankEventFieldNumber:
883       case FtraceEvent::kDrmVblankEventDeliveredFieldNumber:
884       case FtraceEvent::kDrmSchedJobFieldNumber:
885       case FtraceEvent::kDrmRunJobFieldNumber:
886       case FtraceEvent::kDrmSchedProcessJobFieldNumber:
887       case FtraceEvent::kDmaFenceInitFieldNumber:
888       case FtraceEvent::kDmaFenceEmitFieldNumber:
889       case FtraceEvent::kDmaFenceSignaledFieldNumber:
890       case FtraceEvent::kDmaFenceWaitStartFieldNumber:
891       case FtraceEvent::kDmaFenceWaitEndFieldNumber: {
892         drm_tracker_.ParseDrm(ts, fld.id(), pid, fld_bytes);
893         break;
894       }
895       case FtraceEvent::kF2fsIostatFieldNumber: {
896         iostat_tracker_.ParseF2fsIostat(ts, fld_bytes);
897         break;
898       }
899       case FtraceEvent::kF2fsIostatLatencyFieldNumber: {
900         iostat_tracker_.ParseF2fsIostatLatency(ts, fld_bytes);
901         break;
902       }
903       case FtraceEvent::kSchedCpuUtilCfsFieldNumber: {
904         ParseSchedCpuUtilCfs(ts, fld_bytes);
905         break;
906       }
907       case FtraceEvent::kI2cReadFieldNumber: {
908         ParseI2cReadEvent(ts, pid, fld_bytes);
909         break;
910       }
911       case FtraceEvent::kI2cWriteFieldNumber: {
912         ParseI2cWriteEvent(ts, pid, fld_bytes);
913         break;
914       }
915       case FtraceEvent::kI2cResultFieldNumber: {
916         ParseI2cResultEvent(ts, pid, fld_bytes);
917         break;
918       }
919       case FtraceEvent::kFuncgraphEntryFieldNumber: {
920         ParseFuncgraphEntry(ts, pid, fld_bytes, seq_state);
921         break;
922       }
923       case FtraceEvent::kFuncgraphExitFieldNumber: {
924         ParseFuncgraphExit(ts, pid, fld_bytes, seq_state);
925         break;
926       }
927       case FtraceEvent::kV4l2QbufFieldNumber:
928       case FtraceEvent::kV4l2DqbufFieldNumber:
929       case FtraceEvent::kVb2V4l2BufQueueFieldNumber:
930       case FtraceEvent::kVb2V4l2BufDoneFieldNumber:
931       case FtraceEvent::kVb2V4l2QbufFieldNumber:
932       case FtraceEvent::kVb2V4l2DqbufFieldNumber: {
933         V4l2Tracker::GetOrCreate(context_)->ParseV4l2Event(fld.id(), ts, pid,
934                                                            fld_bytes);
935         break;
936       }
937       case FtraceEvent::kVirtioVideoCmdFieldNumber:
938       case FtraceEvent::kVirtioVideoCmdDoneFieldNumber:
939       case FtraceEvent::kVirtioVideoResourceQueueFieldNumber:
940       case FtraceEvent::kVirtioVideoResourceQueueDoneFieldNumber: {
941         VirtioVideoTracker::GetOrCreate(context_)->ParseVirtioVideoEvent(
942             fld.id(), ts, fld_bytes);
943         break;
944       }
945       case FtraceEvent::kTrustySmcFieldNumber: {
946         ParseTrustySmc(pid, ts, fld_bytes);
947         break;
948       }
949       case FtraceEvent::kTrustySmcDoneFieldNumber: {
950         ParseTrustySmcDone(pid, ts, fld_bytes);
951         break;
952       }
953       case FtraceEvent::kTrustyStdCall32FieldNumber: {
954         ParseTrustyStdCall32(pid, ts, fld_bytes);
955         break;
956       }
957       case FtraceEvent::kTrustyStdCall32DoneFieldNumber: {
958         ParseTrustyStdCall32Done(pid, ts, fld_bytes);
959         break;
960       }
961       case FtraceEvent::kTrustyShareMemoryFieldNumber: {
962         ParseTrustyShareMemory(pid, ts, fld_bytes);
963         break;
964       }
965       case FtraceEvent::kTrustyShareMemoryDoneFieldNumber: {
966         ParseTrustyShareMemoryDone(pid, ts, fld_bytes);
967         break;
968       }
969       case FtraceEvent::kTrustyReclaimMemoryFieldNumber: {
970         ParseTrustyReclaimMemory(pid, ts, fld_bytes);
971         break;
972       }
973       case FtraceEvent::kTrustyReclaimMemoryDoneFieldNumber: {
974         ParseTrustyReclaimMemoryDone(pid, ts, fld_bytes);
975         break;
976       }
977       case FtraceEvent::kTrustyIrqFieldNumber: {
978         ParseTrustyIrq(pid, ts, fld_bytes);
979         break;
980       }
981       case FtraceEvent::kTrustyIpcHandleEventFieldNumber: {
982         ParseTrustyIpcHandleEvent(pid, ts, fld_bytes);
983         break;
984       }
985       case FtraceEvent::kTrustyIpcConnectFieldNumber: {
986         ParseTrustyIpcConnect(pid, ts, fld_bytes);
987         break;
988       }
989       case FtraceEvent::kTrustyIpcConnectEndFieldNumber: {
990         ParseTrustyIpcConnectEnd(pid, ts, fld_bytes);
991         break;
992       }
993       case FtraceEvent::kTrustyIpcWriteFieldNumber: {
994         ParseTrustyIpcWrite(pid, ts, fld_bytes);
995         break;
996       }
997       case FtraceEvent::kTrustyIpcReadFieldNumber: {
998         ParseTrustyIpcRead(pid, ts, fld_bytes);
999         break;
1000       }
1001       case FtraceEvent::kTrustyIpcReadEndFieldNumber: {
1002         ParseTrustyIpcReadEnd(pid, ts, fld_bytes);
1003         break;
1004       }
1005       case FtraceEvent::kTrustyIpcPollFieldNumber: {
1006         ParseTrustyIpcPoll(pid, ts, fld_bytes);
1007         break;
1008       }
1009       case FtraceEvent::kTrustyIpcRxFieldNumber: {
1010         ParseTrustyIpcRx(pid, ts, fld_bytes);
1011         break;
1012       }
1013       case FtraceEvent::kTrustyEnqueueNopFieldNumber: {
1014         ParseTrustyEnqueueNop(pid, ts, fld_bytes);
1015         break;
1016       }
1017       case FtraceEvent::kMaliMaliKCPUCQSSETFieldNumber:
1018       case FtraceEvent::kMaliMaliKCPUCQSWAITSTARTFieldNumber:
1019       case FtraceEvent::kMaliMaliKCPUCQSWAITENDFieldNumber:
1020       case FtraceEvent::kMaliMaliKCPUFENCESIGNALFieldNumber:
1021       case FtraceEvent::kMaliMaliKCPUFENCEWAITSTARTFieldNumber:
1022       case FtraceEvent::kMaliMaliKCPUFENCEWAITENDFieldNumber: {
1023         mali_gpu_event_tracker_.ParseMaliGpuEvent(ts, fld.id(), pid);
1024         break;
1025       }
1026       case FtraceEvent::kMaliMaliCSFINTERRUPTSTARTFieldNumber:
1027       case FtraceEvent::kMaliMaliCSFINTERRUPTENDFieldNumber: {
1028         mali_gpu_event_tracker_.ParseMaliGpuIrqEvent(ts, fld.id(), cpu,
1029                                                      fld_bytes);
1030         break;
1031       }
1032 
1033       default:
1034         break;
1035     }
1036   }
1037 
1038   PERFETTO_DCHECK(!decoder.bytes_left());
1039   return util::OkStatus();
1040 }
ParseInlineSchedSwitch(uint32_t cpu,int64_t ts,const InlineSchedSwitch & data)1041 util::Status FtraceParser::ParseInlineSchedSwitch(
1042     uint32_t cpu,
1043     int64_t ts,
1044     const InlineSchedSwitch& data) {
1045   MaybeOnFirstFtraceEvent();
1046   if (PERFETTO_UNLIKELY(ts < drop_ftrace_data_before_ts_)) {
1047     context_->storage->IncrementStats(
1048         stats::ftrace_packet_before_tracing_start);
1049     return util::OkStatus();
1050   }
1051 
1052   using protos::pbzero::FtraceEvent;
1053   SchedEventTracker* sched_tracker = SchedEventTracker::GetOrCreate(context_);
1054   sched_tracker->PushSchedSwitchCompact(cpu, ts, data.prev_state,
1055                                         static_cast<uint32_t>(data.next_pid),
1056                                         data.next_prio, data.next_comm);
1057   return util::OkStatus();
1058 }
1059 
ParseInlineSchedWaking(uint32_t cpu,int64_t ts,const InlineSchedWaking & data)1060 util::Status FtraceParser::ParseInlineSchedWaking(
1061     uint32_t cpu,
1062     int64_t ts,
1063     const InlineSchedWaking& data) {
1064   MaybeOnFirstFtraceEvent();
1065   if (PERFETTO_UNLIKELY(ts < drop_ftrace_data_before_ts_)) {
1066     context_->storage->IncrementStats(
1067         stats::ftrace_packet_before_tracing_start);
1068     return util::OkStatus();
1069   }
1070   using protos::pbzero::FtraceEvent;
1071   SchedEventTracker* sched_tracker = SchedEventTracker::GetOrCreate(context_);
1072   sched_tracker->PushSchedWakingCompact(cpu, ts,
1073                                         static_cast<uint32_t>(data.pid),
1074                                         data.target_cpu, data.prio, data.comm);
1075   return util::OkStatus();
1076 }
1077 
MaybeOnFirstFtraceEvent()1078 void FtraceParser::MaybeOnFirstFtraceEvent() {
1079   if (PERFETTO_LIKELY(has_seen_first_ftrace_packet_)) {
1080     return;
1081   }
1082 
1083   DropFtraceDataBefore drop_before =
1084       preserve_ftrace_buffer_ ? DropFtraceDataBefore::kNoDrop
1085                               : context_->config.drop_ftrace_data_before;
1086   switch (drop_before) {
1087     case DropFtraceDataBefore::kNoDrop: {
1088       drop_ftrace_data_before_ts_ = 0;
1089       break;
1090     }
1091     case DropFtraceDataBefore::kAllDataSourcesStarted:
1092     case DropFtraceDataBefore::kTracingStarted: {
1093       metadata::KeyId event_key =
1094           drop_before == DropFtraceDataBefore::kAllDataSourcesStarted
1095               ? metadata::all_data_source_started_ns
1096               : metadata::tracing_started_ns;
1097       const auto& metadata = context_->storage->metadata_table();
1098       std::optional<uint32_t> opt_row =
1099           metadata.name().IndexOf(metadata::kNames[event_key]);
1100       if (opt_row) {
1101         drop_ftrace_data_before_ts_ = *metadata.int_value()[*opt_row];
1102       }
1103       break;
1104     }
1105   }
1106   has_seen_first_ftrace_packet_ = true;
1107 }
1108 
ParseGenericFtrace(int64_t ts,uint32_t cpu,uint32_t tid,ConstBytes blob)1109 void FtraceParser::ParseGenericFtrace(int64_t ts,
1110                                       uint32_t cpu,
1111                                       uint32_t tid,
1112                                       ConstBytes blob) {
1113   protos::pbzero::GenericFtraceEvent::Decoder evt(blob.data, blob.size);
1114   StringId event_id = context_->storage->InternString(evt.event_name());
1115   UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
1116   RawId id = context_->storage->mutable_ftrace_event_table()
1117                  ->Insert({ts, event_id, cpu, utid})
1118                  .id;
1119   auto inserter = context_->args_tracker->AddArgsTo(id);
1120 
1121   for (auto it = evt.field(); it; ++it) {
1122     protos::pbzero::GenericFtraceEvent::Field::Decoder fld(*it);
1123     auto field_name_id = context_->storage->InternString(fld.name());
1124     if (fld.has_int_value()) {
1125       inserter.AddArg(field_name_id, Variadic::Integer(fld.int_value()));
1126     } else if (fld.has_uint_value()) {
1127       inserter.AddArg(
1128           field_name_id,
1129           Variadic::Integer(static_cast<int64_t>(fld.uint_value())));
1130     } else if (fld.has_str_value()) {
1131       StringId str_value = context_->storage->InternString(fld.str_value());
1132       inserter.AddArg(field_name_id, Variadic::String(str_value));
1133     }
1134   }
1135 }
1136 
ParseTypedFtraceToRaw(uint32_t ftrace_id,int64_t timestamp,uint32_t cpu,uint32_t tid,ConstBytes blob,PacketSequenceStateGeneration * seq_state)1137 void FtraceParser::ParseTypedFtraceToRaw(
1138     uint32_t ftrace_id,
1139     int64_t timestamp,
1140     uint32_t cpu,
1141     uint32_t tid,
1142     ConstBytes blob,
1143     PacketSequenceStateGeneration* seq_state) {
1144   if (PERFETTO_UNLIKELY(!context_->config.ingest_ftrace_in_raw_table))
1145     return;
1146 
1147   ProtoDecoder decoder(blob.data, blob.size);
1148   if (ftrace_id >= GetDescriptorsSize()) {
1149     PERFETTO_DLOG("Event with id: %d does not exist and cannot be parsed.",
1150                   ftrace_id);
1151     return;
1152   }
1153 
1154   FtraceMessageDescriptor* m = GetMessageDescriptorForId(ftrace_id);
1155   const auto& message_strings = ftrace_message_strings_[ftrace_id];
1156   UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
1157   RawId id =
1158       context_->storage->mutable_ftrace_event_table()
1159           ->Insert({timestamp, message_strings.message_name_id, cpu, utid})
1160           .id;
1161   auto inserter = context_->args_tracker->AddArgsTo(id);
1162 
1163   for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
1164     uint16_t field_id = fld.id();
1165     if (PERFETTO_UNLIKELY(field_id >= kMaxFtraceEventFields)) {
1166       PERFETTO_DLOG(
1167           "Skipping ftrace arg - proto field id is too large (%" PRIu16 ")",
1168           field_id);
1169       continue;
1170     }
1171 
1172     ProtoSchemaType type = m->fields[field_id].type;
1173     StringId name_id = message_strings.field_name_ids[field_id];
1174 
1175     // Check if this field represents a kernel function.
1176     auto it = std::find_if(
1177         kKernelFunctionFields.begin(), kKernelFunctionFields.end(),
1178         [ftrace_id, field_id](const FtraceEventAndFieldId& ev) {
1179           return ev.event_id == ftrace_id && ev.field_id == field_id;
1180         });
1181     if (it != kKernelFunctionFields.end()) {
1182       PERFETTO_CHECK(type == ProtoSchemaType::kUint64);
1183 
1184       auto* interned_string = seq_state->LookupInternedMessage<
1185           protos::pbzero::InternedData::kKernelSymbolsFieldNumber,
1186           protos::pbzero::InternedString>(fld.as_uint64());
1187 
1188       // If we don't have the string for this field (can happen if
1189       // symbolization wasn't enabled, if reading the symbols errored out or
1190       // on legacy traces) then just add the field as a normal arg.
1191       if (interned_string) {
1192         protozero::ConstBytes str = interned_string->str();
1193         StringId str_id = context_->storage->InternString(base::StringView(
1194             reinterpret_cast<const char*>(str.data), str.size));
1195         inserter.AddArg(name_id, Variadic::String(str_id));
1196         continue;
1197       }
1198     }
1199 
1200     switch (type) {
1201       case ProtoSchemaType::kInt32:
1202       case ProtoSchemaType::kInt64:
1203       case ProtoSchemaType::kSfixed32:
1204       case ProtoSchemaType::kSfixed64:
1205       case ProtoSchemaType::kSint32:
1206       case ProtoSchemaType::kSint64:
1207       case ProtoSchemaType::kBool:
1208       case ProtoSchemaType::kEnum: {
1209         inserter.AddArg(name_id, Variadic::Integer(fld.as_int64()));
1210         break;
1211       }
1212       case ProtoSchemaType::kUint32:
1213       case ProtoSchemaType::kUint64:
1214       case ProtoSchemaType::kFixed32:
1215       case ProtoSchemaType::kFixed64: {
1216         // Note that SQLite functions will still treat unsigned values
1217         // as a signed 64 bit integers (but the translation back to ftrace
1218         // refers to this storage directly).
1219         inserter.AddArg(name_id, Variadic::UnsignedInteger(fld.as_uint64()));
1220         break;
1221       }
1222       case ProtoSchemaType::kString:
1223       case ProtoSchemaType::kBytes: {
1224         StringId value = context_->storage->InternString(fld.as_string());
1225         inserter.AddArg(name_id, Variadic::String(value));
1226         break;
1227       }
1228       case ProtoSchemaType::kDouble: {
1229         inserter.AddArg(name_id, Variadic::Real(fld.as_double()));
1230         break;
1231       }
1232       case ProtoSchemaType::kFloat: {
1233         inserter.AddArg(name_id,
1234                         Variadic::Real(static_cast<double>(fld.as_float())));
1235         break;
1236       }
1237       case ProtoSchemaType::kUnknown:
1238       case ProtoSchemaType::kGroup:
1239       case ProtoSchemaType::kMessage:
1240         PERFETTO_DLOG("Could not store %s as a field in args table.",
1241                       ProtoSchemaToString(type));
1242         break;
1243     }
1244   }
1245 }
1246 
1247 PERFETTO_ALWAYS_INLINE
ParseSchedSwitch(uint32_t cpu,int64_t timestamp,ConstBytes blob)1248 void FtraceParser::ParseSchedSwitch(uint32_t cpu,
1249                                     int64_t timestamp,
1250                                     ConstBytes blob) {
1251   protos::pbzero::SchedSwitchFtraceEvent::Decoder ss(blob.data, blob.size);
1252   uint32_t prev_pid = static_cast<uint32_t>(ss.prev_pid());
1253   uint32_t next_pid = static_cast<uint32_t>(ss.next_pid());
1254   SchedEventTracker::GetOrCreate(context_)->PushSchedSwitch(
1255       cpu, timestamp, prev_pid, ss.prev_comm(), ss.prev_prio(), ss.prev_state(),
1256       next_pid, ss.next_comm(), ss.next_prio());
1257 }
1258 
ParseSchedWaking(int64_t timestamp,uint32_t pid,ConstBytes blob)1259 void FtraceParser::ParseSchedWaking(int64_t timestamp,
1260                                     uint32_t pid,
1261                                     ConstBytes blob) {
1262   protos::pbzero::SchedWakingFtraceEvent::Decoder sw(blob.data, blob.size);
1263   uint32_t wakee_pid = static_cast<uint32_t>(sw.pid());
1264   StringId name_id = context_->storage->InternString(sw.comm());
1265   auto wakee_utid = context_->process_tracker->UpdateThreadName(
1266       wakee_pid, name_id, ThreadNamePriority::kFtrace);
1267   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1268   ThreadStateTracker::GetOrCreate(context_)->PushWakingEvent(timestamp,
1269                                                              wakee_utid, utid);
1270 }
1271 
ParseSchedProcessFree(int64_t timestamp,ConstBytes blob)1272 void FtraceParser::ParseSchedProcessFree(int64_t timestamp, ConstBytes blob) {
1273   protos::pbzero::SchedProcessFreeFtraceEvent::Decoder ex(blob.data, blob.size);
1274   uint32_t pid = static_cast<uint32_t>(ex.pid());
1275   context_->process_tracker->EndThread(timestamp, pid);
1276 }
1277 
ParseCpuFreq(int64_t timestamp,ConstBytes blob)1278 void FtraceParser::ParseCpuFreq(int64_t timestamp, ConstBytes blob) {
1279   protos::pbzero::CpuFrequencyFtraceEvent::Decoder freq(blob.data, blob.size);
1280   uint32_t cpu = freq.cpu_id();
1281   uint32_t new_freq = freq.state();
1282   TrackId track =
1283       context_->track_tracker->InternCpuCounterTrack(cpu_freq_name_id_, cpu);
1284   context_->event_tracker->PushCounter(timestamp, new_freq, track);
1285 }
1286 
ParseGpuFreq(int64_t timestamp,ConstBytes blob)1287 void FtraceParser::ParseGpuFreq(int64_t timestamp, ConstBytes blob) {
1288   protos::pbzero::GpuFrequencyFtraceEvent::Decoder freq(blob.data, blob.size);
1289   uint32_t gpu = freq.gpu_id();
1290   uint32_t new_freq = freq.state();
1291   TrackId track =
1292       context_->track_tracker->InternGpuCounterTrack(gpu_freq_name_id_, gpu);
1293   context_->event_tracker->PushCounter(timestamp, new_freq, track);
1294 }
1295 
ParseCpuIdle(int64_t timestamp,ConstBytes blob)1296 void FtraceParser::ParseCpuIdle(int64_t timestamp, ConstBytes blob) {
1297   protos::pbzero::CpuIdleFtraceEvent::Decoder idle(blob.data, blob.size);
1298   uint32_t cpu = idle.cpu_id();
1299   uint32_t new_state = idle.state();
1300   TrackId track =
1301       context_->track_tracker->InternCpuCounterTrack(cpu_idle_name_id_, cpu);
1302   context_->event_tracker->PushCounter(timestamp, new_state, track);
1303 }
1304 
ParsePrint(int64_t timestamp,uint32_t pid,ConstBytes blob)1305 void FtraceParser::ParsePrint(int64_t timestamp,
1306                               uint32_t pid,
1307                               ConstBytes blob) {
1308   // Atrace slices are emitted as begin/end events written into the tracefs
1309   // trace_marker. If we're tracing syscalls, the reconstructed atrace slice
1310   // would start and end in the middle of different sys_write slices (on the
1311   // same track). Since trace_processor enforces strict slice nesting, we need
1312   // to resolve this conflict. The chosen approach is to distort the data, and
1313   // pretend that the write syscall ended at the atrace slice's boundary.
1314   //
1315   // In other words, this true structure:
1316   // [write...].....[write...]
1317   // ....[atrace_slice..].....
1318   //
1319   // Is turned into:
1320   // [wr][atrace_slice..]
1321   // ...............[wri]
1322   //
1323   std::optional<UniqueTid> opt_utid =
1324       context_->process_tracker->GetThreadOrNull(pid);
1325   if (opt_utid) {
1326     SyscallTracker::GetOrCreate(context_)->MaybeTruncateOngoingWriteSlice(
1327         timestamp, *opt_utid);
1328   }
1329 
1330   protos::pbzero::PrintFtraceEvent::Decoder evt(blob.data, blob.size);
1331   SystraceParser::GetOrCreate(context_)->ParsePrintEvent(timestamp, pid,
1332                                                          evt.buf());
1333 }
1334 
ParseZero(int64_t timestamp,uint32_t pid,ConstBytes blob)1335 void FtraceParser::ParseZero(int64_t timestamp, uint32_t pid, ConstBytes blob) {
1336   protos::pbzero::ZeroFtraceEvent::Decoder evt(blob.data, blob.size);
1337   uint32_t tgid = static_cast<uint32_t>(evt.pid());
1338   SystraceParser::GetOrCreate(context_)->ParseZeroEvent(
1339       timestamp, pid, evt.flag(), evt.name(), tgid, evt.value());
1340 }
1341 
ParseSdeTracingMarkWrite(int64_t timestamp,uint32_t pid,ConstBytes blob)1342 void FtraceParser::ParseSdeTracingMarkWrite(int64_t timestamp,
1343                                             uint32_t pid,
1344                                             ConstBytes blob) {
1345   protos::pbzero::SdeTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
1346                                                               blob.size);
1347   if (!evt.has_trace_type() && !evt.has_trace_begin()) {
1348     context_->storage->IncrementStats(stats::systrace_parse_failure);
1349     return;
1350   }
1351 
1352   uint32_t tgid = static_cast<uint32_t>(evt.pid());
1353   SystraceParser::GetOrCreate(context_)->ParseKernelTracingMarkWrite(
1354       timestamp, pid, static_cast<char>(evt.trace_type()), evt.trace_begin(),
1355       evt.trace_name(), tgid, evt.value());
1356 }
1357 
ParseDpuTracingMarkWrite(int64_t timestamp,uint32_t pid,ConstBytes blob)1358 void FtraceParser::ParseDpuTracingMarkWrite(int64_t timestamp,
1359                                             uint32_t pid,
1360                                             ConstBytes blob) {
1361   protos::pbzero::DpuTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
1362                                                               blob.size);
1363   if (!evt.type()) {
1364     context_->storage->IncrementStats(stats::systrace_parse_failure);
1365     return;
1366   }
1367 
1368   uint32_t tgid = static_cast<uint32_t>(evt.pid());
1369   SystraceParser::GetOrCreate(context_)->ParseKernelTracingMarkWrite(
1370       timestamp, pid, static_cast<char>(evt.type()), false /*trace_begin*/,
1371       evt.name(), tgid, evt.value());
1372 }
1373 
ParseG2dTracingMarkWrite(int64_t timestamp,uint32_t pid,ConstBytes blob)1374 void FtraceParser::ParseG2dTracingMarkWrite(int64_t timestamp,
1375                                             uint32_t pid,
1376                                             ConstBytes blob) {
1377   protos::pbzero::G2dTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
1378                                                               blob.size);
1379   if (!evt.type()) {
1380     context_->storage->IncrementStats(stats::systrace_parse_failure);
1381     return;
1382   }
1383 
1384   uint32_t tgid = static_cast<uint32_t>(evt.pid());
1385   SystraceParser::GetOrCreate(context_)->ParseKernelTracingMarkWrite(
1386       timestamp, pid, static_cast<char>(evt.type()), false /*trace_begin*/,
1387       evt.name(), tgid, evt.value());
1388 }
1389 
ParseMaliTracingMarkWrite(int64_t timestamp,uint32_t pid,ConstBytes blob)1390 void FtraceParser::ParseMaliTracingMarkWrite(int64_t timestamp,
1391                                              uint32_t pid,
1392                                              ConstBytes blob) {
1393   protos::pbzero::MaliTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
1394                                                                blob.size);
1395   if (!evt.type()) {
1396     context_->storage->IncrementStats(stats::systrace_parse_failure);
1397     return;
1398   }
1399 
1400   uint32_t tgid = static_cast<uint32_t>(evt.pid());
1401   SystraceParser::GetOrCreate(context_)->ParseKernelTracingMarkWrite(
1402       timestamp, pid, static_cast<char>(evt.type()), false /*trace_begin*/,
1403       evt.name(), tgid, evt.value());
1404 }
1405 
ParseLwisTracingMarkWrite(int64_t timestamp,uint32_t pid,ConstBytes blob)1406 void FtraceParser::ParseLwisTracingMarkWrite(int64_t timestamp,
1407                                              uint32_t pid,
1408                                              ConstBytes blob) {
1409   protos::pbzero::LwisTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
1410                                                                blob.size);
1411   if (!evt.type()) {
1412     context_->storage->IncrementStats(stats::systrace_parse_failure);
1413     return;
1414   }
1415 
1416   uint32_t tgid = static_cast<uint32_t>(evt.pid());
1417   SystraceParser::GetOrCreate(context_)->ParseKernelTracingMarkWrite(
1418       timestamp, pid, static_cast<char>(evt.type()), false /*trace_begin*/,
1419       evt.func_name(), tgid, evt.value());
1420 }
1421 
1422 /** Parses ion heap events present in Pixel kernels. */
ParseIonHeapGrowOrShrink(int64_t timestamp,uint32_t pid,ConstBytes blob,bool grow)1423 void FtraceParser::ParseIonHeapGrowOrShrink(int64_t timestamp,
1424                                             uint32_t pid,
1425                                             ConstBytes blob,
1426                                             bool grow) {
1427   protos::pbzero::IonHeapGrowFtraceEvent::Decoder ion(blob.data, blob.size);
1428   int64_t change_bytes = static_cast<int64_t>(ion.len()) * (grow ? 1 : -1);
1429   // The total_allocated ftrace event reports the value before the
1430   // atomic_long_add / sub takes place.
1431   int64_t total_bytes = ion.total_allocated() + change_bytes;
1432   StringId global_name_id = ion_total_unknown_id_;
1433   StringId change_name_id = ion_change_unknown_id_;
1434 
1435   if (ion.has_heap_name()) {
1436     base::StringView heap_name = ion.heap_name();
1437     base::StackString<255> ion_name("mem.ion.%.*s", int(heap_name.size()),
1438                                     heap_name.data());
1439     global_name_id = context_->storage->InternString(ion_name.string_view());
1440 
1441     base::StackString<255> change_name("mem.ion_change.%.*s",
1442                                        int(heap_name.size()), heap_name.data());
1443     change_name_id = context_->storage->InternString(change_name.string_view());
1444   }
1445 
1446   // Push the global counter.
1447   TrackId track = context_->track_tracker->InternGlobalCounterTrack(
1448       TrackTracker::Group::kMemory, global_name_id);
1449   context_->event_tracker->PushCounter(timestamp,
1450                                        static_cast<double>(total_bytes), track);
1451 
1452   // Push the change counter.
1453   // TODO(b/121331269): these should really be instant events.
1454   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1455   track =
1456       context_->track_tracker->InternThreadCounterTrack(change_name_id, utid);
1457   context_->event_tracker->PushCounter(
1458       timestamp, static_cast<double>(change_bytes), track);
1459 
1460   // We are reusing the same function for ion_heap_grow and ion_heap_shrink.
1461   // It is fine as the arguments are the same, but we need to be sure that the
1462   // protobuf field id for both are the same.
1463   static_assert(
1464       static_cast<int>(
1465           protos::pbzero::IonHeapGrowFtraceEvent::kTotalAllocatedFieldNumber) ==
1466               static_cast<int>(protos::pbzero::IonHeapShrinkFtraceEvent::
1467                                    kTotalAllocatedFieldNumber) &&
1468           static_cast<int>(
1469               protos::pbzero::IonHeapGrowFtraceEvent::kLenFieldNumber) ==
1470               static_cast<int>(
1471                   protos::pbzero::IonHeapShrinkFtraceEvent::kLenFieldNumber) &&
1472           static_cast<int>(
1473               protos::pbzero::IonHeapGrowFtraceEvent::kHeapNameFieldNumber) ==
1474               static_cast<int>(protos::pbzero::IonHeapShrinkFtraceEvent::
1475                                    kHeapNameFieldNumber),
1476       "ION field mismatch");
1477 }
1478 
1479 /** Parses ion heap events (introduced in 4.19 kernels). */
ParseIonStat(int64_t timestamp,uint32_t pid,protozero::ConstBytes data)1480 void FtraceParser::ParseIonStat(int64_t timestamp,
1481                                 uint32_t pid,
1482                                 protozero::ConstBytes data) {
1483   protos::pbzero::IonStatFtraceEvent::Decoder ion(data.data, data.size);
1484   // Push the global counter.
1485   TrackId track = context_->track_tracker->InternGlobalCounterTrack(
1486       TrackTracker::Group::kMemory, ion_total_id_);
1487   context_->event_tracker->PushCounter(
1488       timestamp, static_cast<double>(ion.total_allocated()), track);
1489 
1490   // Push the change counter.
1491   // TODO(b/121331269): these should really be instant events.
1492   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1493   track =
1494       context_->track_tracker->InternThreadCounterTrack(ion_change_id_, utid);
1495   context_->event_tracker->PushCounter(timestamp,
1496                                        static_cast<double>(ion.len()), track);
1497 
1498   // Global track for individual buffer tracking
1499   auto async_track =
1500       context_->async_track_set_tracker->InternGlobalTrackSet(ion_buffer_id_);
1501   if (ion.len() > 0) {
1502     TrackId start_id =
1503         context_->async_track_set_tracker->Begin(async_track, ion.buffer_id());
1504     std::string buf = std::to_string(ion.len() / 1024) + " kB";
1505     context_->slice_tracker->Begin(
1506         timestamp, start_id, kNullStringId,
1507         context_->storage->InternString(base::StringView(buf)));
1508   } else {
1509     TrackId end_id =
1510         context_->async_track_set_tracker->End(async_track, ion.buffer_id());
1511     context_->slice_tracker->End(timestamp, end_id);
1512   }
1513 }
1514 
ParseDmaHeapStat(int64_t timestamp,uint32_t pid,protozero::ConstBytes data)1515 void FtraceParser::ParseDmaHeapStat(int64_t timestamp,
1516                                     uint32_t pid,
1517                                     protozero::ConstBytes data) {
1518   protos::pbzero::DmaHeapStatFtraceEvent::Decoder dma_heap(data.data,
1519                                                            data.size);
1520   // Push the global counter.
1521   TrackId track = context_->track_tracker->InternGlobalCounterTrack(
1522       TrackTracker::Group::kMemory, dma_heap_total_id_);
1523   context_->event_tracker->PushCounter(
1524       timestamp, static_cast<double>(dma_heap.total_allocated()), track);
1525 
1526   // Push the change counter.
1527   // TODO(b/121331269): these should really be instant events.
1528   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1529   track = context_->track_tracker->InternThreadCounterTrack(dma_heap_change_id_,
1530                                                             utid);
1531   context_->event_tracker->PushCounter(
1532       timestamp, static_cast<double>(dma_heap.len()), track);
1533 
1534   // Global track for individual buffer tracking
1535   auto async_track =
1536       context_->async_track_set_tracker->InternGlobalTrackSet(dma_buffer_id_);
1537   if (dma_heap.len() > 0) {
1538     TrackId start_id = context_->async_track_set_tracker->Begin(
1539         async_track, static_cast<int64_t>(dma_heap.inode()));
1540     std::string buf = std::to_string(dma_heap.len() / 1024) + " kB";
1541     context_->slice_tracker->Begin(
1542         timestamp, start_id, kNullStringId,
1543         context_->storage->InternString(base::StringView(buf)));
1544   } else {
1545     TrackId end_id = context_->async_track_set_tracker->End(
1546         async_track, static_cast<int64_t>(dma_heap.inode()));
1547     context_->slice_tracker->End(timestamp, end_id);
1548   }
1549 }
1550 
1551 // This event has both the pid of the thread that sent the signal and the
1552 // destination of the signal. Currently storing the pid of the destination.
ParseSignalGenerate(int64_t timestamp,ConstBytes blob)1553 void FtraceParser::ParseSignalGenerate(int64_t timestamp, ConstBytes blob) {
1554   protos::pbzero::SignalGenerateFtraceEvent::Decoder sig(blob.data, blob.size);
1555 
1556   UniqueTid utid = context_->process_tracker->GetOrCreateThread(
1557       static_cast<uint32_t>(sig.pid()));
1558   int signal = sig.sig();
1559   TrackId track = context_->track_tracker->InternThreadTrack(utid);
1560   context_->slice_tracker->Scoped(
1561       timestamp, track, kNullStringId, signal_generate_id_, 0,
1562       [this, signal](ArgsTracker::BoundInserter* inserter) {
1563         inserter->AddArg(signal_name_id_, Variadic::Integer(signal));
1564       });
1565 }
1566 
ParseSignalDeliver(int64_t timestamp,uint32_t pid,ConstBytes blob)1567 void FtraceParser::ParseSignalDeliver(int64_t timestamp,
1568                                       uint32_t pid,
1569                                       ConstBytes blob) {
1570   protos::pbzero::SignalDeliverFtraceEvent::Decoder sig(blob.data, blob.size);
1571   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1572   int signal = sig.sig();
1573   TrackId track = context_->track_tracker->InternThreadTrack(utid);
1574   context_->slice_tracker->Scoped(
1575       timestamp, track, kNullStringId, signal_deliver_id_, 0,
1576       [this, signal](ArgsTracker::BoundInserter* inserter) {
1577         inserter->AddArg(signal_name_id_, Variadic::Integer(signal));
1578       });
1579 }
1580 
ParseOOMScoreAdjUpdate(int64_t timestamp,ConstBytes blob)1581 void FtraceParser::ParseOOMScoreAdjUpdate(int64_t timestamp, ConstBytes blob) {
1582   protos::pbzero::OomScoreAdjUpdateFtraceEvent::Decoder evt(blob.data,
1583                                                             blob.size);
1584   // The int16_t static cast is because older version of the on-device tracer
1585   // had a bug on negative varint encoding (b/120618641).
1586   int16_t oom_adj = static_cast<int16_t>(evt.oom_score_adj());
1587   uint32_t tid = static_cast<uint32_t>(evt.pid());
1588   UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
1589   context_->event_tracker->PushProcessCounterForThread(timestamp, oom_adj,
1590                                                        oom_score_adj_id_, utid);
1591 }
1592 
ParseOOMKill(int64_t timestamp,ConstBytes blob)1593 void FtraceParser::ParseOOMKill(int64_t timestamp, ConstBytes blob) {
1594   protos::pbzero::MarkVictimFtraceEvent::Decoder evt(blob.data, blob.size);
1595   UniqueTid utid = context_->process_tracker->GetOrCreateThread(
1596       static_cast<uint32_t>(evt.pid()));
1597   TrackId track = context_->track_tracker->InternThreadTrack(utid);
1598   context_->slice_tracker->Scoped(timestamp, track, kNullStringId, oom_kill_id_,
1599                                   0);
1600 }
1601 
ParseMmEventRecord(int64_t timestamp,uint32_t pid,ConstBytes blob)1602 void FtraceParser::ParseMmEventRecord(int64_t timestamp,
1603                                       uint32_t pid,
1604                                       ConstBytes blob) {
1605   protos::pbzero::MmEventRecordFtraceEvent::Decoder evt(blob.data, blob.size);
1606   uint32_t type = evt.type();
1607   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1608 
1609   if (type >= mm_event_counter_names_.size()) {
1610     context_->storage->IncrementStats(stats::mm_unknown_type);
1611     return;
1612   }
1613 
1614   const auto& counter_names = mm_event_counter_names_[type];
1615   context_->event_tracker->PushProcessCounterForThread(
1616       timestamp, evt.count(), counter_names.count, utid);
1617   context_->event_tracker->PushProcessCounterForThread(
1618       timestamp, evt.max_lat(), counter_names.max_lat, utid);
1619   context_->event_tracker->PushProcessCounterForThread(
1620       timestamp, evt.avg_lat(), counter_names.avg_lat, utid);
1621 }
1622 
ParseSysEnterEvent(int64_t timestamp,uint32_t pid,ConstBytes blob)1623 void FtraceParser::ParseSysEnterEvent(int64_t timestamp,
1624                                       uint32_t pid,
1625                                       ConstBytes blob) {
1626   protos::pbzero::SysEnterFtraceEvent::Decoder evt(blob.data, blob.size);
1627   uint32_t syscall_num = static_cast<uint32_t>(evt.id());
1628   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1629 
1630   SyscallTracker* syscall_tracker = SyscallTracker::GetOrCreate(context_);
1631   auto args_callback = [this, &evt](ArgsTracker::BoundInserter* inserter) {
1632     // process all syscall arguments
1633     uint32_t count = 0;
1634     for (auto it = evt.args(); it; ++it) {
1635       if (syscall_arg_name_ids_.size() == count) {
1636         base::StackString<32> string_arg("args[%" PRId32 "]", count);
1637         auto string_id =
1638             context_->storage->InternString(string_arg.string_view());
1639         syscall_arg_name_ids_.emplace_back(string_id);
1640       }
1641       inserter->AddArg(syscall_args_id_, syscall_arg_name_ids_[count],
1642                        Variadic::UnsignedInteger(*it));
1643       ++count;
1644     }
1645   };
1646   syscall_tracker->Enter(timestamp, utid, syscall_num, args_callback);
1647 }
1648 
ParseSysExitEvent(int64_t timestamp,uint32_t pid,ConstBytes blob)1649 void FtraceParser::ParseSysExitEvent(int64_t timestamp,
1650                                      uint32_t pid,
1651                                      ConstBytes blob) {
1652   // Note: Although this seems duplicated to ParseSysEnterEvent, it is
1653   //       not. We decode SysExitFtraceEvent here to handle the return
1654   //       value of a syscall whereas SysEnterFtraceEvent is decoded
1655   //       above to handle the syscall arguments.
1656   protos::pbzero::SysExitFtraceEvent::Decoder evt(blob.data, blob.size);
1657   uint32_t syscall_num = static_cast<uint32_t>(evt.id());
1658   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1659 
1660   SyscallTracker* syscall_tracker = SyscallTracker::GetOrCreate(context_);
1661   auto args_callback = [this, &evt](ArgsTracker::BoundInserter* inserter) {
1662     if (evt.has_ret()) {
1663       const auto ret = evt.ret();
1664       inserter->AddArg(syscall_ret_id_, Variadic::Integer(ret));
1665     }
1666   };
1667   syscall_tracker->Exit(timestamp, utid, syscall_num, args_callback);
1668 }
1669 
ParseI2cReadEvent(int64_t timestamp,uint32_t pid,protozero::ConstBytes blob)1670 void FtraceParser::ParseI2cReadEvent(int64_t timestamp,
1671                                      uint32_t pid,
1672                                      protozero::ConstBytes blob) {
1673   protos::pbzero::I2cReadFtraceEvent::Decoder evt(blob.data, blob.size);
1674   uint32_t adapter_nr = static_cast<uint32_t>(evt.adapter_nr());
1675   uint32_t msg_nr = static_cast<uint32_t>(evt.msg_nr());
1676   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1677 
1678   I2cTracker* i2c_tracker = I2cTracker::GetOrCreate(context_);
1679   i2c_tracker->Enter(timestamp, utid, adapter_nr, msg_nr);
1680 }
1681 
ParseI2cWriteEvent(int64_t timestamp,uint32_t pid,protozero::ConstBytes blob)1682 void FtraceParser::ParseI2cWriteEvent(int64_t timestamp,
1683                                       uint32_t pid,
1684                                       protozero::ConstBytes blob) {
1685   protos::pbzero::I2cWriteFtraceEvent::Decoder evt(blob.data, blob.size);
1686   uint32_t adapter_nr = static_cast<uint32_t>(evt.adapter_nr());
1687   uint32_t msg_nr = static_cast<uint32_t>(evt.msg_nr());
1688   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1689 
1690   I2cTracker* i2c_tracker = I2cTracker::GetOrCreate(context_);
1691   i2c_tracker->Enter(timestamp, utid, adapter_nr, msg_nr);
1692 }
1693 
ParseI2cResultEvent(int64_t timestamp,uint32_t pid,protozero::ConstBytes blob)1694 void FtraceParser::ParseI2cResultEvent(int64_t timestamp,
1695                                        uint32_t pid,
1696                                        protozero::ConstBytes blob) {
1697   protos::pbzero::I2cResultFtraceEvent::Decoder evt(blob.data, blob.size);
1698   uint32_t adapter_nr = static_cast<uint32_t>(evt.adapter_nr());
1699   uint32_t nr_msgs = static_cast<uint32_t>(evt.nr_msgs());
1700   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1701 
1702   I2cTracker* i2c_tracker = I2cTracker::GetOrCreate(context_);
1703   i2c_tracker->Exit(timestamp, utid, adapter_nr, nr_msgs);
1704 }
1705 
ParseTaskNewTask(int64_t timestamp,uint32_t source_tid,ConstBytes blob)1706 void FtraceParser::ParseTaskNewTask(int64_t timestamp,
1707                                     uint32_t source_tid,
1708                                     ConstBytes blob) {
1709   protos::pbzero::TaskNewtaskFtraceEvent::Decoder evt(blob.data, blob.size);
1710   uint32_t clone_flags = static_cast<uint32_t>(evt.clone_flags());
1711   uint32_t new_tid = static_cast<uint32_t>(evt.pid());
1712   StringId new_comm = context_->storage->InternString(evt.comm());
1713   auto* proc_tracker = context_->process_tracker.get();
1714 
1715   // task_newtask is raised both in the case of a new process creation (fork()
1716   // family) and thread creation (clone(CLONE_THREAD, ...)).
1717   static const uint32_t kCloneThread = 0x00010000;  // From kernel's sched.h.
1718 
1719   // If the process is a fork, start a new process.
1720   if ((clone_flags & kCloneThread) == 0) {
1721     // This is a plain-old fork() or equivalent.
1722     proc_tracker->StartNewProcess(timestamp, source_tid, new_tid, new_comm,
1723                                   ThreadNamePriority::kFtrace);
1724     return;
1725   }
1726 
1727   // This is a pthread_create or similar. Bind the two threads together, so
1728   // they get resolved to the same process.
1729   auto source_utid = proc_tracker->GetOrCreateThread(source_tid);
1730   auto new_utid = proc_tracker->StartNewThread(timestamp, new_tid);
1731   proc_tracker->UpdateThreadNameByUtid(new_utid, new_comm,
1732                                        ThreadNamePriority::kFtrace);
1733   proc_tracker->AssociateThreads(source_utid, new_utid);
1734 
1735   ThreadStateTracker::GetOrCreate(context_)->PushNewTaskEvent(
1736       timestamp, new_utid, source_utid);
1737 }
1738 
ParseTaskRename(ConstBytes blob)1739 void FtraceParser::ParseTaskRename(ConstBytes blob) {
1740   protos::pbzero::TaskRenameFtraceEvent::Decoder evt(blob.data, blob.size);
1741   uint32_t tid = static_cast<uint32_t>(evt.pid());
1742   StringId comm = context_->storage->InternString(evt.newcomm());
1743   context_->process_tracker->UpdateThreadNameAndMaybeProcessName(
1744       tid, comm, ThreadNamePriority::kFtrace);
1745 }
1746 
ParseBinderTransaction(int64_t timestamp,uint32_t pid,ConstBytes blob)1747 void FtraceParser::ParseBinderTransaction(int64_t timestamp,
1748                                           uint32_t pid,
1749                                           ConstBytes blob) {
1750   protos::pbzero::BinderTransactionFtraceEvent::Decoder evt(blob.data,
1751                                                             blob.size);
1752   int32_t dest_node = static_cast<int32_t>(evt.target_node());
1753   uint32_t dest_tgid = static_cast<uint32_t>(evt.to_proc());
1754   uint32_t dest_tid = static_cast<uint32_t>(evt.to_thread());
1755   int32_t transaction_id = static_cast<int32_t>(evt.debug_id());
1756   bool is_reply = static_cast<int32_t>(evt.reply()) == 1;
1757   uint32_t flags = static_cast<uint32_t>(evt.flags());
1758   auto code_str = base::IntToHexString(evt.code()) + " Java Layer Dependent";
1759   StringId code = context_->storage->InternString(base::StringView(code_str));
1760   BinderTracker::GetOrCreate(context_)->Transaction(
1761       timestamp, pid, transaction_id, dest_node, dest_tgid, dest_tid, is_reply,
1762       flags, code);
1763 }
1764 
ParseBinderTransactionReceived(int64_t timestamp,uint32_t pid,ConstBytes blob)1765 void FtraceParser::ParseBinderTransactionReceived(int64_t timestamp,
1766                                                   uint32_t pid,
1767                                                   ConstBytes blob) {
1768   protos::pbzero::BinderTransactionReceivedFtraceEvent::Decoder evt(blob.data,
1769                                                                     blob.size);
1770   int32_t transaction_id = static_cast<int32_t>(evt.debug_id());
1771   BinderTracker::GetOrCreate(context_)->TransactionReceived(timestamp, pid,
1772                                                             transaction_id);
1773 }
1774 
ParseBinderTransactionAllocBuf(int64_t timestamp,uint32_t pid,ConstBytes blob)1775 void FtraceParser::ParseBinderTransactionAllocBuf(int64_t timestamp,
1776                                                   uint32_t pid,
1777                                                   ConstBytes blob) {
1778   protos::pbzero::BinderTransactionAllocBufFtraceEvent::Decoder evt(blob.data,
1779                                                                     blob.size);
1780   uint64_t data_size = static_cast<uint64_t>(evt.data_size());
1781   uint64_t offsets_size = static_cast<uint64_t>(evt.offsets_size());
1782 
1783   BinderTracker::GetOrCreate(context_)->TransactionAllocBuf(
1784       timestamp, pid, data_size, offsets_size);
1785 }
1786 
ParseBinderLocked(int64_t timestamp,uint32_t pid,ConstBytes blob)1787 void FtraceParser::ParseBinderLocked(int64_t timestamp,
1788                                      uint32_t pid,
1789                                      ConstBytes blob) {
1790   protos::pbzero::BinderLockedFtraceEvent::Decoder evt(blob.data, blob.size);
1791   BinderTracker::GetOrCreate(context_)->Locked(timestamp, pid);
1792 }
1793 
ParseBinderLock(int64_t timestamp,uint32_t pid,ConstBytes blob)1794 void FtraceParser::ParseBinderLock(int64_t timestamp,
1795                                    uint32_t pid,
1796                                    ConstBytes blob) {
1797   protos::pbzero::BinderLockFtraceEvent::Decoder evt(blob.data, blob.size);
1798   BinderTracker::GetOrCreate(context_)->Lock(timestamp, pid);
1799 }
1800 
ParseBinderUnlock(int64_t timestamp,uint32_t pid,ConstBytes blob)1801 void FtraceParser::ParseBinderUnlock(int64_t timestamp,
1802                                      uint32_t pid,
1803                                      ConstBytes blob) {
1804   protos::pbzero::BinderUnlockFtraceEvent::Decoder evt(blob.data, blob.size);
1805   BinderTracker::GetOrCreate(context_)->Unlock(timestamp, pid);
1806 }
1807 
ParseClockSetRate(int64_t timestamp,ConstBytes blob)1808 void FtraceParser::ParseClockSetRate(int64_t timestamp, ConstBytes blob) {
1809   protos::pbzero::ClockSetRateFtraceEvent::Decoder evt(blob.data, blob.size);
1810   static const char kSubtitle[] = "Frequency";
1811   ClockRate(timestamp, evt.name(), kSubtitle, evt.state());
1812 }
1813 
ParseClockEnable(int64_t timestamp,ConstBytes blob)1814 void FtraceParser::ParseClockEnable(int64_t timestamp, ConstBytes blob) {
1815   protos::pbzero::ClockEnableFtraceEvent::Decoder evt(blob.data, blob.size);
1816   static const char kSubtitle[] = "State";
1817   ClockRate(timestamp, evt.name(), kSubtitle, evt.state());
1818 }
1819 
ParseClockDisable(int64_t timestamp,ConstBytes blob)1820 void FtraceParser::ParseClockDisable(int64_t timestamp, ConstBytes blob) {
1821   protos::pbzero::ClockDisableFtraceEvent::Decoder evt(blob.data, blob.size);
1822   static const char kSubtitle[] = "State";
1823   ClockRate(timestamp, evt.name(), kSubtitle, evt.state());
1824 }
1825 
ClockRate(int64_t timestamp,base::StringView clock_name,base::StringView subtitle,uint64_t rate)1826 void FtraceParser::ClockRate(int64_t timestamp,
1827                              base::StringView clock_name,
1828                              base::StringView subtitle,
1829                              uint64_t rate) {
1830   base::StackString<255> counter_name("%.*s %.*s", int(clock_name.size()),
1831                                       clock_name.data(), int(subtitle.size()),
1832                                       subtitle.data());
1833   StringId name = context_->storage->InternString(counter_name.c_str());
1834   TrackId track = context_->track_tracker->InternGlobalCounterTrack(
1835       TrackTracker::Group::kClockFrequency, name);
1836   context_->event_tracker->PushCounter(timestamp, static_cast<double>(rate),
1837                                        track);
1838 }
1839 
ParseScmCallStart(int64_t timestamp,uint32_t pid,ConstBytes blob)1840 void FtraceParser::ParseScmCallStart(int64_t timestamp,
1841                                      uint32_t pid,
1842                                      ConstBytes blob) {
1843   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1844   TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
1845   protos::pbzero::ScmCallStartFtraceEvent::Decoder evt(blob.data, blob.size);
1846 
1847   base::StackString<64> str("scm id=%#" PRIx64, evt.x0());
1848   StringId name_id = context_->storage->InternString(str.string_view());
1849   context_->slice_tracker->Begin(timestamp, track_id, kNullStringId, name_id);
1850 }
1851 
ParseScmCallEnd(int64_t timestamp,uint32_t pid,ConstBytes blob)1852 void FtraceParser::ParseScmCallEnd(int64_t timestamp,
1853                                    uint32_t pid,
1854                                    ConstBytes blob) {
1855   protos::pbzero::ScmCallEndFtraceEvent::Decoder evt(blob.data, blob.size);
1856   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1857   TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
1858   context_->slice_tracker->End(timestamp, track_id);
1859 }
1860 
ParseCmaAllocStart(int64_t timestamp,uint32_t pid)1861 void FtraceParser::ParseCmaAllocStart(int64_t timestamp, uint32_t pid) {
1862   std::optional<VersionNumber> kernel_version =
1863       SystemInfoTracker::GetOrCreate(context_)->GetKernelVersion();
1864   // CmaAllocInfo event only exists after 5.10
1865   if (kernel_version < VersionNumber{5, 10})
1866     return;
1867 
1868   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1869   TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
1870 
1871   context_->slice_tracker->Begin(timestamp, track_id, kNullStringId,
1872                                  cma_alloc_id_);
1873 }
1874 
ParseCmaAllocInfo(int64_t timestamp,uint32_t pid,ConstBytes blob)1875 void FtraceParser::ParseCmaAllocInfo(int64_t timestamp,
1876                                      uint32_t pid,
1877                                      ConstBytes blob) {
1878   std::optional<VersionNumber> kernel_version =
1879       SystemInfoTracker::GetOrCreate(context_)->GetKernelVersion();
1880   // CmaAllocInfo event only exists after 5.10
1881   if (kernel_version < VersionNumber{5, 10})
1882     return;
1883 
1884   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1885   TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
1886   protos::pbzero::CmaAllocInfoFtraceEvent::Decoder cma_alloc_info(blob.data,
1887                                                                   blob.size);
1888   auto args_inserter = [this,
1889                         &cma_alloc_info](ArgsTracker::BoundInserter* inserter) {
1890     inserter->AddArg(cma_name_id_,
1891                      Variadic::String(context_->storage->InternString(
1892                          cma_alloc_info.name())));
1893     inserter->AddArg(cma_pfn_id_,
1894                      Variadic::UnsignedInteger(cma_alloc_info.pfn()));
1895     inserter->AddArg(cma_req_pages_id_,
1896                      Variadic::UnsignedInteger(cma_alloc_info.count()));
1897     inserter->AddArg(cma_nr_migrated_id_,
1898                      Variadic::UnsignedInteger(cma_alloc_info.nr_migrated()));
1899     inserter->AddArg(cma_nr_reclaimed_id_,
1900                      Variadic::UnsignedInteger(cma_alloc_info.nr_reclaimed()));
1901     inserter->AddArg(cma_nr_mapped_id_,
1902                      Variadic::UnsignedInteger(cma_alloc_info.nr_mapped()));
1903     inserter->AddArg(cma_nr_isolate_fail_id_,
1904                      Variadic::UnsignedInteger(cma_alloc_info.err_iso()));
1905     inserter->AddArg(cma_nr_migrate_fail_id_,
1906                      Variadic::UnsignedInteger(cma_alloc_info.err_mig()));
1907     inserter->AddArg(cma_nr_test_fail_id_,
1908                      Variadic::UnsignedInteger(cma_alloc_info.err_test()));
1909   };
1910   context_->slice_tracker->End(timestamp, track_id, kNullStringId,
1911                                kNullStringId, args_inserter);
1912 }
1913 
ParseDirectReclaimBegin(int64_t timestamp,uint32_t pid,ConstBytes blob)1914 void FtraceParser::ParseDirectReclaimBegin(int64_t timestamp,
1915                                            uint32_t pid,
1916                                            ConstBytes blob) {
1917   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1918   TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
1919   protos::pbzero::MmVmscanDirectReclaimBeginFtraceEvent::Decoder
1920       direct_reclaim_begin(blob.data, blob.size);
1921 
1922   StringId name_id =
1923       context_->storage->InternString("mm_vmscan_direct_reclaim");
1924 
1925   auto args_inserter = [this, &direct_reclaim_begin](
1926                            ArgsTracker::BoundInserter* inserter) {
1927     inserter->AddArg(direct_reclaim_order_id_,
1928                      Variadic::Integer(direct_reclaim_begin.order()));
1929     inserter->AddArg(direct_reclaim_may_writepage_id_,
1930                      Variadic::Integer(direct_reclaim_begin.may_writepage()));
1931     inserter->AddArg(
1932         direct_reclaim_gfp_flags_id_,
1933         Variadic::UnsignedInteger(direct_reclaim_begin.gfp_flags()));
1934   };
1935   context_->slice_tracker->Begin(timestamp, track_id, kNullStringId, name_id,
1936                                  args_inserter);
1937 }
1938 
ParseDirectReclaimEnd(int64_t timestamp,uint32_t pid,ConstBytes blob)1939 void FtraceParser::ParseDirectReclaimEnd(int64_t timestamp,
1940                                          uint32_t pid,
1941                                          ConstBytes blob) {
1942   protos::pbzero::ScmCallEndFtraceEvent::Decoder evt(blob.data, blob.size);
1943   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1944   TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
1945   protos::pbzero::MmVmscanDirectReclaimEndFtraceEvent::Decoder
1946       direct_reclaim_end(blob.data, blob.size);
1947 
1948   auto args_inserter =
1949       [this, &direct_reclaim_end](ArgsTracker::BoundInserter* inserter) {
1950         inserter->AddArg(
1951             direct_reclaim_nr_reclaimed_id_,
1952             Variadic::UnsignedInteger(direct_reclaim_end.nr_reclaimed()));
1953       };
1954   context_->slice_tracker->End(timestamp, track_id, kNullStringId,
1955                                kNullStringId, args_inserter);
1956 }
1957 
ParseShrinkSlabStart(int64_t timestamp,uint32_t pid,ConstBytes blob,PacketSequenceStateGeneration * seq_state)1958 void FtraceParser::ParseShrinkSlabStart(
1959     int64_t timestamp,
1960     uint32_t pid,
1961     ConstBytes blob,
1962     PacketSequenceStateGeneration* seq_state) {
1963   protos::pbzero::MmShrinkSlabStartFtraceEvent::Decoder shrink_slab_start(
1964       blob.data, blob.size);
1965 
1966   StringId shrink_name =
1967       InternedKernelSymbolOrFallback(shrink_slab_start.shrink(), seq_state);
1968 
1969   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1970   TrackId track = context_->track_tracker->InternThreadTrack(utid);
1971 
1972   auto args_inserter = [this, &shrink_slab_start,
1973                         shrink_name](ArgsTracker::BoundInserter* inserter) {
1974     inserter->AddArg(shrink_name_id_, Variadic::String(shrink_name));
1975     inserter->AddArg(shrink_total_scan_id_,
1976                      Variadic::UnsignedInteger(shrink_slab_start.total_scan()));
1977     inserter->AddArg(shrink_priority_id_,
1978                      Variadic::Integer(shrink_slab_start.priority()));
1979   };
1980 
1981   context_->slice_tracker->Begin(timestamp, track, kNullStringId,
1982                                  shrink_slab_id_, args_inserter);
1983 }
1984 
ParseShrinkSlabEnd(int64_t timestamp,uint32_t pid,ConstBytes blob)1985 void FtraceParser::ParseShrinkSlabEnd(int64_t timestamp,
1986                                       uint32_t pid,
1987                                       ConstBytes blob) {
1988   protos::pbzero::MmShrinkSlabEndFtraceEvent::Decoder shrink_slab_end(
1989       blob.data, blob.size);
1990   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1991   TrackId track = context_->track_tracker->InternThreadTrack(utid);
1992 
1993   auto args_inserter =
1994       [this, &shrink_slab_end](ArgsTracker::BoundInserter* inserter) {
1995         inserter->AddArg(shrink_freed_id_,
1996                          Variadic::Integer(shrink_slab_end.retval()));
1997       };
1998   context_->slice_tracker->End(timestamp, track, kNullStringId, kNullStringId,
1999                                args_inserter);
2000 }
2001 
ParseWorkqueueExecuteStart(uint32_t cpu,int64_t timestamp,uint32_t pid,ConstBytes blob,PacketSequenceStateGeneration * seq_state)2002 void FtraceParser::ParseWorkqueueExecuteStart(
2003     uint32_t cpu,
2004     int64_t timestamp,
2005     uint32_t pid,
2006     ConstBytes blob,
2007     PacketSequenceStateGeneration* seq_state) {
2008   protos::pbzero::WorkqueueExecuteStartFtraceEvent::Decoder evt(blob.data,
2009                                                                 blob.size);
2010   StringId name_id = InternedKernelSymbolOrFallback(evt.function(), seq_state);
2011 
2012   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2013   TrackId track = context_->track_tracker->InternThreadTrack(utid);
2014 
2015   auto args_inserter = [this, cpu](ArgsTracker::BoundInserter* inserter) {
2016     inserter->AddArg(cpu_id_, Variadic::Integer(cpu));
2017   };
2018   context_->slice_tracker->Begin(timestamp, track, workqueue_id_, name_id,
2019                                  args_inserter);
2020 }
2021 
ParseWorkqueueExecuteEnd(int64_t timestamp,uint32_t pid,ConstBytes blob)2022 void FtraceParser::ParseWorkqueueExecuteEnd(int64_t timestamp,
2023                                             uint32_t pid,
2024                                             ConstBytes blob) {
2025   protos::pbzero::WorkqueueExecuteEndFtraceEvent::Decoder evt(blob.data,
2026                                                               blob.size);
2027   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2028   TrackId track = context_->track_tracker->InternThreadTrack(utid);
2029   context_->slice_tracker->End(timestamp, track, workqueue_id_);
2030 }
2031 
ParseIrqHandlerEntry(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)2032 void FtraceParser::ParseIrqHandlerEntry(uint32_t cpu,
2033                                         int64_t timestamp,
2034                                         protozero::ConstBytes blob) {
2035   protos::pbzero::IrqHandlerEntryFtraceEvent::Decoder evt(blob.data, blob.size);
2036   base::StackString<255> track_name("Irq Cpu %d", cpu);
2037   StringId track_name_id =
2038       context_->storage->InternString(track_name.string_view());
2039 
2040   base::StringView irq_name = evt.name();
2041   base::StackString<255> slice_name("IRQ (%.*s)", int(irq_name.size()),
2042                                     irq_name.data());
2043   StringId slice_name_id =
2044       context_->storage->InternString(slice_name.string_view());
2045   TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
2046   context_->slice_tracker->Begin(timestamp, track, irq_id_, slice_name_id);
2047 }
2048 
ParseIrqHandlerExit(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)2049 void FtraceParser::ParseIrqHandlerExit(uint32_t cpu,
2050                                        int64_t timestamp,
2051                                        protozero::ConstBytes blob) {
2052   protos::pbzero::IrqHandlerExitFtraceEvent::Decoder evt(blob.data, blob.size);
2053   base::StackString<255> track_name("Irq Cpu %d", cpu);
2054   StringId track_name_id =
2055       context_->storage->InternString(track_name.string_view());
2056   TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
2057 
2058   base::StackString<255> status("%s", evt.ret() == 1 ? "handled" : "unhandled");
2059   StringId status_id = context_->storage->InternString(status.string_view());
2060   auto args_inserter = [this,
2061                         &status_id](ArgsTracker::BoundInserter* inserter) {
2062     inserter->AddArg(ret_arg_id_, Variadic::String(status_id));
2063   };
2064   context_->slice_tracker->End(timestamp, track, irq_id_, {}, args_inserter);
2065 }
2066 
ParseSoftIrqEntry(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)2067 void FtraceParser::ParseSoftIrqEntry(uint32_t cpu,
2068                                      int64_t timestamp,
2069                                      protozero::ConstBytes blob) {
2070   protos::pbzero::SoftirqEntryFtraceEvent::Decoder evt(blob.data, blob.size);
2071   base::StackString<255> track_name("SoftIrq Cpu %d", cpu);
2072   StringId track_name_id =
2073       context_->storage->InternString(track_name.string_view());
2074   auto num_actions = sizeof(kActionNames) / sizeof(*kActionNames);
2075   if (evt.vec() >= num_actions) {
2076     PERFETTO_DFATAL("No action name at index %d for softirq event.", evt.vec());
2077     return;
2078   }
2079   base::StringView slice_name = kActionNames[evt.vec()];
2080   StringId slice_name_id = context_->storage->InternString(slice_name);
2081   TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
2082   context_->slice_tracker->Begin(timestamp, track, irq_id_, slice_name_id);
2083 }
2084 
ParseSoftIrqExit(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)2085 void FtraceParser::ParseSoftIrqExit(uint32_t cpu,
2086                                     int64_t timestamp,
2087                                     protozero::ConstBytes blob) {
2088   protos::pbzero::SoftirqExitFtraceEvent::Decoder evt(blob.data, blob.size);
2089   base::StackString<255> track_name("SoftIrq Cpu %d", cpu);
2090   StringId track_name_id =
2091       context_->storage->InternString(track_name.string_view());
2092   TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
2093   auto vec = evt.vec();
2094   auto args_inserter = [this, vec](ArgsTracker::BoundInserter* inserter) {
2095     inserter->AddArg(vec_arg_id_, Variadic::Integer(vec));
2096   };
2097   context_->slice_tracker->End(timestamp, track, irq_id_, {}, args_inserter);
2098 }
2099 
ParseGpuMemTotal(int64_t timestamp,protozero::ConstBytes data)2100 void FtraceParser::ParseGpuMemTotal(int64_t timestamp,
2101                                     protozero::ConstBytes data) {
2102   protos::pbzero::GpuMemTotalFtraceEvent::Decoder gpu_mem_total(data.data,
2103                                                                 data.size);
2104 
2105   TrackId track = kInvalidTrackId;
2106   const uint32_t pid = gpu_mem_total.pid();
2107   if (pid == 0) {
2108     // Pid 0 is used to indicate the global total
2109     track = context_->track_tracker->InternGlobalCounterTrack(
2110         TrackTracker::Group::kMemory, gpu_mem_total_name_id_, {},
2111         gpu_mem_total_unit_id_, gpu_mem_total_global_desc_id_);
2112   } else {
2113     // It's possible for GpuMemTotal ftrace events to be emitted by kworker
2114     // threads *after* process death. In this case, we simply want to discard
2115     // the event as otherwise we would create fake processes which we
2116     // definitely want to avoid.
2117     // See b/192274404 for more info.
2118     std::optional<UniqueTid> opt_utid =
2119         context_->process_tracker->GetThreadOrNull(pid);
2120     if (!opt_utid)
2121       return;
2122 
2123     // If the thread does exist, the |pid| in gpu_mem_total events is always a
2124     // true process id (and not a thread id) so ensure there is an association
2125     // between the tid and pid.
2126     UniqueTid updated_utid = context_->process_tracker->UpdateThread(pid, pid);
2127     PERFETTO_DCHECK(updated_utid == *opt_utid);
2128 
2129     // UpdateThread above should ensure this is always set.
2130     UniquePid upid = *context_->storage->thread_table().upid()[*opt_utid];
2131     PERFETTO_DCHECK(context_->storage->process_table().pid()[upid] == pid);
2132 
2133     track = context_->track_tracker->InternProcessCounterTrack(
2134         gpu_mem_total_name_id_, upid, gpu_mem_total_unit_id_,
2135         gpu_mem_total_proc_desc_id_);
2136   }
2137   context_->event_tracker->PushCounter(
2138       timestamp, static_cast<double>(gpu_mem_total.size()), track);
2139 }
2140 
ParseThermalTemperature(int64_t timestamp,protozero::ConstBytes blob)2141 void FtraceParser::ParseThermalTemperature(int64_t timestamp,
2142                                            protozero::ConstBytes blob) {
2143   protos::pbzero::ThermalTemperatureFtraceEvent::Decoder event(blob.data,
2144                                                                blob.size);
2145   base::StringView thermal_zone = event.thermal_zone();
2146   base::StackString<255> counter_name(
2147       "%.*s Temperature", int(thermal_zone.size()), thermal_zone.data());
2148   StringId name = context_->storage->InternString(counter_name.string_view());
2149   TrackId track = context_->track_tracker->InternGlobalCounterTrack(
2150       TrackTracker::Group::kThermals, name);
2151   context_->event_tracker->PushCounter(timestamp, event.temp(), track);
2152 }
2153 
ParseCdevUpdate(int64_t timestamp,protozero::ConstBytes blob)2154 void FtraceParser::ParseCdevUpdate(int64_t timestamp,
2155                                    protozero::ConstBytes blob) {
2156   protos::pbzero::CdevUpdateFtraceEvent::Decoder event(blob.data, blob.size);
2157   base::StringView type = event.type();
2158   base::StackString<255> counter_name("%.*s Cooling Device", int(type.size()),
2159                                       type.data());
2160   StringId name = context_->storage->InternString(counter_name.string_view());
2161   TrackId track = context_->track_tracker->InternGlobalCounterTrack(
2162       TrackTracker::Group::kThermals, name);
2163   context_->event_tracker->PushCounter(
2164       timestamp, static_cast<double>(event.target()), track);
2165 }
2166 
ParseSchedBlockedReason(protozero::ConstBytes blob,PacketSequenceStateGeneration * seq_state)2167 void FtraceParser::ParseSchedBlockedReason(
2168     protozero::ConstBytes blob,
2169     PacketSequenceStateGeneration* seq_state) {
2170   protos::pbzero::SchedBlockedReasonFtraceEvent::Decoder event(blob);
2171   uint32_t pid = static_cast<uint32_t>(event.pid());
2172   auto utid = context_->process_tracker->GetOrCreateThread(pid);
2173   uint32_t caller_iid = static_cast<uint32_t>(event.caller());
2174   auto* interned_string = seq_state->LookupInternedMessage<
2175       protos::pbzero::InternedData::kKernelSymbolsFieldNumber,
2176       protos::pbzero::InternedString>(caller_iid);
2177 
2178   std::optional<StringId> blocked_function_str_id = std::nullopt;
2179   if (interned_string) {
2180     protozero::ConstBytes str = interned_string->str();
2181     blocked_function_str_id = context_->storage->InternString(
2182         base::StringView(reinterpret_cast<const char*>(str.data), str.size));
2183   }
2184 
2185   ThreadStateTracker::GetOrCreate(context_)->PushBlockedReason(
2186       utid, event.io_wait(), blocked_function_str_id);
2187 }
2188 
ParseFastRpcDmaStat(int64_t timestamp,uint32_t pid,protozero::ConstBytes blob)2189 void FtraceParser::ParseFastRpcDmaStat(int64_t timestamp,
2190                                        uint32_t pid,
2191                                        protozero::ConstBytes blob) {
2192   protos::pbzero::FastrpcDmaStatFtraceEvent::Decoder event(blob.data,
2193                                                            blob.size);
2194 
2195   StringId name;
2196   if (0 <= event.cid() &&
2197       event.cid() < static_cast<int32_t>(kFastRpcCounterSize)) {
2198     name = fast_rpc_delta_names_[static_cast<size_t>(event.cid())];
2199   } else {
2200     base::StackString<64> str("mem.fastrpc[%" PRId32 "]", event.cid());
2201     name = context_->storage->InternString(str.string_view());
2202   }
2203 
2204   StringId total_name;
2205   if (0 <= event.cid() &&
2206       event.cid() < static_cast<int32_t>(kFastRpcCounterSize)) {
2207     total_name = fast_rpc_total_names_[static_cast<size_t>(event.cid())];
2208   } else {
2209     base::StackString<64> str("mem.fastrpc[%" PRId32 "]", event.cid());
2210     total_name = context_->storage->InternString(str.string_view());
2211   }
2212 
2213   // Push the global counter.
2214   TrackId track = context_->track_tracker->InternGlobalCounterTrack(
2215       TrackTracker::Group::kMemory, total_name);
2216   context_->event_tracker->PushCounter(
2217       timestamp, static_cast<double>(event.total_allocated()), track);
2218 
2219   // Push the change counter.
2220   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2221   TrackId delta_track =
2222       context_->track_tracker->InternThreadCounterTrack(name, utid);
2223   context_->event_tracker->PushCounter(
2224       timestamp, static_cast<double>(event.len()), delta_track);
2225 }
2226 
ParseCpuhpPause(int64_t,uint32_t,protozero::ConstBytes blob)2227 void FtraceParser::ParseCpuhpPause(int64_t,
2228                                    uint32_t,
2229                                    protozero::ConstBytes blob) {
2230   protos::pbzero::CpuhpPauseFtraceEvent::Decoder evt(blob.data, blob.size);
2231   // TODO(b/183110813): Parse and visualize this event.
2232 }
2233 
ParseNetifReceiveSkb(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)2234 void FtraceParser::ParseNetifReceiveSkb(uint32_t cpu,
2235                                         int64_t timestamp,
2236                                         protozero::ConstBytes blob) {
2237   protos::pbzero::NetifReceiveSkbFtraceEvent::Decoder event(blob.data,
2238                                                             blob.size);
2239   base::StringView net_device = event.name();
2240   base::StackString<255> counter_name("%.*s Received KB",
2241                                       static_cast<int>(net_device.size()),
2242                                       net_device.data());
2243   StringId name = context_->storage->InternString(counter_name.string_view());
2244 
2245   nic_received_bytes_[name] += event.len();
2246 
2247   uint64_t nic_received_kilobytes = nic_received_bytes_[name] / 1024;
2248   TrackId track = context_->track_tracker->InternGlobalCounterTrack(
2249       TrackTracker::Group::kNetwork, name);
2250   std::optional<CounterId> id = context_->event_tracker->PushCounter(
2251       timestamp, static_cast<double>(nic_received_kilobytes), track);
2252   if (!id) {
2253     return;
2254   }
2255   // Store cpu & len as args for metrics computation
2256   StringId cpu_key = context_->storage->InternString("cpu");
2257   StringId len_key = context_->storage->InternString("len");
2258   context_->args_tracker->AddArgsTo(*id)
2259       .AddArg(cpu_key, Variadic::UnsignedInteger(cpu))
2260       .AddArg(len_key, Variadic::UnsignedInteger(event.len()));
2261 }
2262 
ParseNetDevXmit(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)2263 void FtraceParser::ParseNetDevXmit(uint32_t cpu,
2264                                    int64_t timestamp,
2265                                    protozero::ConstBytes blob) {
2266   protos::pbzero::NetDevXmitFtraceEvent::Decoder evt(blob.data, blob.size);
2267   base::StringView net_device = evt.name();
2268   base::StackString<255> counter_name("%.*s Transmitted KB",
2269                                       static_cast<int>(net_device.size()),
2270                                       net_device.data());
2271   StringId name = context_->storage->InternString(counter_name.string_view());
2272 
2273   // Make sure driver took care of packet.
2274   if (evt.rc() != 0) {
2275     return;
2276   }
2277   nic_transmitted_bytes_[name] += evt.len();
2278 
2279   uint64_t nic_transmitted_kilobytes = nic_transmitted_bytes_[name] / 1024;
2280   TrackId track = context_->track_tracker->InternGlobalCounterTrack(
2281       TrackTracker::Group::kNetwork, name);
2282   std::optional<CounterId> id = context_->event_tracker->PushCounter(
2283       timestamp, static_cast<double>(nic_transmitted_kilobytes), track);
2284   if (!id) {
2285     return;
2286   }
2287   // Store cpu & len as args for metrics computation.
2288   context_->args_tracker->AddArgsTo(*id)
2289       .AddArg(cpu_id_, Variadic::UnsignedInteger(cpu))
2290       .AddArg(len_arg_id_, Variadic::UnsignedInteger(evt.len()));
2291 }
2292 
ParseInetSockSetState(int64_t timestamp,uint32_t pid,protozero::ConstBytes blob)2293 void FtraceParser::ParseInetSockSetState(int64_t timestamp,
2294                                          uint32_t pid,
2295                                          protozero::ConstBytes blob) {
2296   protos::pbzero::InetSockSetStateFtraceEvent::Decoder evt(blob.data,
2297                                                            blob.size);
2298 
2299   // Skip non TCP protocol.
2300   if (evt.protocol() != kIpprotoTcp) {
2301     PERFETTO_ELOG("skip non tcp protocol");
2302     return;
2303   }
2304 
2305   // Skip non IP protocol.
2306   if (evt.family() != kAfNet && evt.family() != kAfNet6) {
2307     PERFETTO_ELOG("skip non IP protocol");
2308     return;
2309   }
2310 
2311   // Skip invalid TCP state.
2312   if (evt.newstate() >= TCP_MAX_STATES || evt.oldstate() >= TCP_MAX_STATES) {
2313     PERFETTO_ELOG("skip invalid tcp state");
2314     return;
2315   }
2316 
2317   auto got = skaddr_to_stream_.find(evt.skaddr());
2318   if (got == skaddr_to_stream_.end()) {
2319     skaddr_to_stream_[evt.skaddr()] = ++num_of_tcp_stream_;
2320   }
2321   uint32_t stream = skaddr_to_stream_[evt.skaddr()];
2322   base::StackString<64> stream_str("TCP stream#%" PRIu32 "", stream);
2323   StringId stream_id =
2324       context_->storage->InternString(stream_str.string_view());
2325 
2326   StringId slice_name_id;
2327   if (evt.newstate() == TCP_SYN_SENT) {
2328     base::StackString<32> str("%s(pid=%" PRIu32 ")",
2329                               kTcpStateNames[evt.newstate()], pid);
2330     slice_name_id = context_->storage->InternString(str.string_view());
2331   } else if (evt.newstate() == TCP_ESTABLISHED) {
2332     base::StackString<64> str("%s(sport=%" PRIu32 ",dport=%" PRIu32 ")",
2333                               kTcpStateNames[evt.newstate()], evt.sport(),
2334                               evt.dport());
2335     slice_name_id = context_->storage->InternString(str.string_view());
2336   } else {
2337     base::StringView slice_name = kTcpStateNames[evt.newstate()];
2338     slice_name_id = context_->storage->InternString(slice_name);
2339   }
2340 
2341   // Push to async task set tracker.
2342   auto async_track =
2343       context_->async_track_set_tracker->InternGlobalTrackSet(stream_id);
2344   TrackId end_id = context_->async_track_set_tracker->End(
2345       async_track, static_cast<int64_t>(evt.skaddr()));
2346   context_->slice_tracker->End(timestamp, end_id);
2347   TrackId start_id = context_->async_track_set_tracker->Begin(
2348       async_track, static_cast<int64_t>(evt.skaddr()));
2349   context_->slice_tracker->Begin(timestamp, start_id, tcp_state_id_,
2350                                  slice_name_id);
2351 }
2352 
ParseTcpRetransmitSkb(int64_t timestamp,protozero::ConstBytes blob)2353 void FtraceParser::ParseTcpRetransmitSkb(int64_t timestamp,
2354                                          protozero::ConstBytes blob) {
2355   protos::pbzero::TcpRetransmitSkbFtraceEvent::Decoder evt(blob.data,
2356                                                            blob.size);
2357 
2358   // Push event as instant to async task set tracker.
2359   auto async_track = context_->async_track_set_tracker->InternGlobalTrackSet(
2360       tcp_retransmited_name_id_);
2361   base::StackString<64> str("sport=%" PRIu32 ",dport=%" PRIu32 "", evt.sport(),
2362                             evt.dport());
2363   StringId slice_name_id = context_->storage->InternString(str.string_view());
2364   TrackId track_id =
2365       context_->async_track_set_tracker->Scoped(async_track, timestamp, 0);
2366   context_->slice_tracker->Scoped(timestamp, track_id, tcp_event_id_,
2367                                   slice_name_id, 0);
2368 }
2369 
ParseNapiGroReceiveEntry(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)2370 void FtraceParser::ParseNapiGroReceiveEntry(uint32_t cpu,
2371                                             int64_t timestamp,
2372                                             protozero::ConstBytes blob) {
2373   protos::pbzero::NapiGroReceiveEntryFtraceEvent::Decoder evt(blob.data,
2374                                                               blob.size);
2375   base::StackString<255> track_name("Napi Gro Cpu %d", cpu);
2376   StringId track_name_id =
2377       context_->storage->InternString(track_name.string_view());
2378   base::StringView net_device = evt.name();
2379   StringId slice_name_id = context_->storage->InternString(net_device);
2380   TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
2381   auto len = evt.len();
2382   auto args_inserter = [this, len](ArgsTracker::BoundInserter* inserter) {
2383     inserter->AddArg(len_arg_id_, Variadic::Integer(len));
2384   };
2385   context_->slice_tracker->Begin(timestamp, track, napi_gro_id_, slice_name_id,
2386                                  args_inserter);
2387 }
2388 
ParseNapiGroReceiveExit(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)2389 void FtraceParser::ParseNapiGroReceiveExit(uint32_t cpu,
2390                                            int64_t timestamp,
2391                                            protozero::ConstBytes blob) {
2392   protos::pbzero::NapiGroReceiveExitFtraceEvent::Decoder evt(blob.data,
2393                                                              blob.size);
2394   base::StackString<255> track_name("Napi Gro Cpu %d", cpu);
2395   StringId track_name_id =
2396       context_->storage->InternString(track_name.string_view());
2397   TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
2398   auto ret = evt.ret();
2399   auto args_inserter = [this, ret](ArgsTracker::BoundInserter* inserter) {
2400     inserter->AddArg(ret_arg_id_, Variadic::Integer(ret));
2401   };
2402   context_->slice_tracker->End(timestamp, track, napi_gro_id_, {},
2403                                args_inserter);
2404 }
2405 
ParseCpuFrequencyLimits(int64_t timestamp,protozero::ConstBytes blob)2406 void FtraceParser::ParseCpuFrequencyLimits(int64_t timestamp,
2407                                            protozero::ConstBytes blob) {
2408   protos::pbzero::CpuFrequencyLimitsFtraceEvent::Decoder evt(blob.data,
2409                                                              blob.size);
2410   base::StackString<255> max_counter_name("Cpu %" PRIu32 " Max Freq Limit",
2411                                           evt.cpu_id());
2412   base::StackString<255> min_counter_name("Cpu %" PRIu32 " Min Freq Limit",
2413                                           evt.cpu_id());
2414   // Push max freq to global counter.
2415   StringId max_name = context_->storage->InternString(max_counter_name.c_str());
2416   TrackId max_track =
2417       context_->track_tracker->InternCpuCounterTrack(max_name, evt.cpu_id());
2418   context_->event_tracker->PushCounter(
2419       timestamp, static_cast<double>(evt.max_freq()), max_track);
2420 
2421   // Push min freq to global counter.
2422   StringId min_name = context_->storage->InternString(min_counter_name.c_str());
2423   TrackId min_track =
2424       context_->track_tracker->InternCpuCounterTrack(min_name, evt.cpu_id());
2425   context_->event_tracker->PushCounter(
2426       timestamp, static_cast<double>(evt.min_freq()), min_track);
2427 }
2428 
ParseKfreeSkb(int64_t timestamp,protozero::ConstBytes blob)2429 void FtraceParser::ParseKfreeSkb(int64_t timestamp,
2430                                  protozero::ConstBytes blob) {
2431   protos::pbzero::KfreeSkbFtraceEvent::Decoder evt(blob.data, blob.size);
2432 
2433   // Skip non IP & IPV6 protocol.
2434   if (evt.protocol() != kEthPIp && evt.protocol() != kEthPIp6) {
2435     return;
2436   }
2437   num_of_kfree_skb_ip_prot += 1;
2438 
2439   TrackId track = context_->track_tracker->InternGlobalCounterTrack(
2440       TrackTracker::Group::kNetwork, kfree_skb_name_id_);
2441   std::optional<CounterId> id = context_->event_tracker->PushCounter(
2442       timestamp, static_cast<double>(num_of_kfree_skb_ip_prot), track);
2443   if (!id) {
2444     return;
2445   }
2446   base::StackString<255> prot("%s", evt.protocol() == kEthPIp ? "IP" : "IPV6");
2447   StringId prot_id = context_->storage->InternString(prot.string_view());
2448   // Store protocol as args for metrics computation.
2449   context_->args_tracker->AddArgsTo(*id).AddArg(protocol_arg_id_,
2450                                                 Variadic::String(prot_id));
2451 }
2452 
ParseCrosEcSensorhubData(int64_t timestamp,protozero::ConstBytes blob)2453 void FtraceParser::ParseCrosEcSensorhubData(int64_t timestamp,
2454                                             protozero::ConstBytes blob) {
2455   protos::pbzero::CrosEcSensorhubDataFtraceEvent::Decoder evt(blob.data,
2456                                                               blob.size);
2457 
2458   // Push the global counter.
2459   TrackId track = context_->track_tracker->InternGlobalCounterTrack(
2460       TrackTracker::Group::kDeviceState,
2461       context_->storage->InternString(
2462           base::StringView("cros_ec.cros_ec_sensorhub_data." +
2463                            std::to_string(evt.ec_sensor_num()))));
2464 
2465   auto args_inserter = [this, &evt](ArgsTracker::BoundInserter* inserter) {
2466     inserter->AddArg(cros_ec_arg_num_id_,
2467                      Variadic::Integer(evt.ec_sensor_num()));
2468     inserter->AddArg(
2469         cros_ec_arg_ec_id_,
2470         Variadic::Integer(evt.fifo_timestamp() - evt.current_timestamp()));
2471     inserter->AddArg(cros_ec_arg_sample_ts_id_,
2472                      Variadic::Integer(evt.current_timestamp()));
2473   };
2474 
2475   context_->event_tracker->PushCounter(
2476       timestamp,
2477       static_cast<double>(evt.current_time() - evt.current_timestamp()), track,
2478       args_inserter);
2479 }
2480 
ParseUfshcdClkGating(int64_t timestamp,protozero::ConstBytes blob)2481 void FtraceParser::ParseUfshcdClkGating(int64_t timestamp,
2482                                         protozero::ConstBytes blob) {
2483   protos::pbzero::UfshcdClkGatingFtraceEvent::Decoder evt(blob.data, blob.size);
2484   int32_t clk_state = 0;
2485 
2486   switch (evt.state()) {
2487     case 1:
2488       // Change ON state to 3
2489       clk_state = 3;
2490       break;
2491     case 2:
2492       // Change REQ_OFF state to 1
2493       clk_state = 1;
2494       break;
2495     case 3:
2496       // Change REQ_ON state to 2
2497       clk_state = 2;
2498       break;
2499   }
2500   TrackId track = context_->track_tracker->InternGlobalCounterTrack(
2501       TrackTracker::Group::kNetwork, ufs_clkgating_id_);
2502   context_->event_tracker->PushCounter(timestamp,
2503                                        static_cast<double>(clk_state), track);
2504 }
2505 
ParseTrustySmc(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2506 void FtraceParser::ParseTrustySmc(uint32_t pid,
2507                                   int64_t timestamp,
2508                                   protozero::ConstBytes blob) {
2509   protos::pbzero::TrustySmcFtraceEvent::Decoder evt(blob.data, blob.size);
2510 
2511   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2512   TrackId track = context_->track_tracker->InternThreadTrack(utid);
2513 
2514   base::StackString<48> name("trusty_smc:r0= %" PRIu64, evt.r0());
2515   StringId name_generic = context_->storage->InternString(name.string_view());
2516 
2517   context_->slice_tracker->Begin(timestamp, track, trusty_category_id_,
2518                                  name_generic);
2519 }
2520 
ParseTrustySmcDone(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2521 void FtraceParser::ParseTrustySmcDone(uint32_t pid,
2522                                       int64_t timestamp,
2523                                       protozero::ConstBytes blob) {
2524   protos::pbzero::TrustySmcDoneFtraceEvent::Decoder evt(blob.data, blob.size);
2525 
2526   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2527   TrackId track = context_->track_tracker->InternThreadTrack(utid);
2528 
2529   context_->slice_tracker->End(timestamp, track, trusty_category_id_);
2530   base::StackString<256> name("trusty_smc_done:r0= %" PRIu64, evt.ret());
2531   StringId name_generic = context_->storage->InternString(name.string_view());
2532   context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2533                                   name_generic, 0);
2534 }
2535 
ParseTrustyStdCall32(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2536 void FtraceParser::ParseTrustyStdCall32(uint32_t pid,
2537                                         int64_t timestamp,
2538                                         protozero::ConstBytes blob) {
2539   protos::pbzero::TrustyStdCall32FtraceEvent::Decoder evt(blob.data, blob.size);
2540 
2541   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2542   TrackId track = context_->track_tracker->InternThreadTrack(utid);
2543 
2544   context_->slice_tracker->Begin(timestamp, track, trusty_category_id_,
2545                                  trusty_name_trusty_std_id_);
2546 }
2547 
ParseTrustyStdCall32Done(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2548 void FtraceParser::ParseTrustyStdCall32Done(uint32_t pid,
2549                                             int64_t timestamp,
2550                                             protozero::ConstBytes blob) {
2551   protos::pbzero::TrustyStdCall32DoneFtraceEvent::Decoder evt(blob.data,
2552                                                               blob.size);
2553 
2554   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2555   TrackId track = context_->track_tracker->InternThreadTrack(utid);
2556 
2557   context_->slice_tracker->End(timestamp, track, trusty_category_id_);
2558   if (evt.ret() < 0) {
2559     base::StackString<256> name("trusty_err_std: err= %" PRIi64, evt.ret());
2560     StringId name_generic = context_->storage->InternString(name.string_view());
2561     context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2562                                     name_generic, 0);
2563   }
2564 }
2565 
ParseTrustyShareMemory(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2566 void FtraceParser::ParseTrustyShareMemory(uint32_t pid,
2567                                           int64_t timestamp,
2568                                           protozero::ConstBytes blob) {
2569   protos::pbzero::TrustyShareMemoryFtraceEvent::Decoder evt(blob.data,
2570                                                             blob.size);
2571 
2572   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2573   TrackId track = context_->track_tracker->InternThreadTrack(utid);
2574 
2575   base::StackString<256> name(
2576       "trusty_share_mem: len= %" PRIu64 " nents= %" PRIu32 " lend= %" PRIu32,
2577       static_cast<uint64_t>(evt.len()), evt.nents(), evt.lend());
2578   StringId name_generic = context_->storage->InternString(name.string_view());
2579 
2580   context_->slice_tracker->Begin(timestamp, track, trusty_category_id_,
2581                                  name_generic);
2582 }
2583 
ParseTrustyShareMemoryDone(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2584 void FtraceParser::ParseTrustyShareMemoryDone(uint32_t pid,
2585                                               int64_t timestamp,
2586                                               protozero::ConstBytes blob) {
2587   protos::pbzero::TrustyShareMemoryDoneFtraceEvent::Decoder evt(blob.data,
2588                                                                 blob.size);
2589 
2590   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2591   TrackId track = context_->track_tracker->InternThreadTrack(utid);
2592   context_->slice_tracker->End(timestamp, track, trusty_category_id_);
2593 
2594   base::StackString<256> name("trusty_share_mem: handle= %" PRIu64
2595                               " ret= %" PRIi32,
2596                               evt.handle(), evt.ret());
2597   StringId name_generic = context_->storage->InternString(name.string_view());
2598   context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2599                                   name_generic, 0);
2600 }
2601 
ParseTrustyReclaimMemory(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2602 void FtraceParser::ParseTrustyReclaimMemory(uint32_t pid,
2603                                             int64_t timestamp,
2604                                             protozero::ConstBytes blob) {
2605   protos::pbzero::TrustyReclaimMemoryFtraceEvent::Decoder evt(blob.data,
2606                                                               blob.size);
2607 
2608   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2609   TrackId track = context_->track_tracker->InternThreadTrack(utid);
2610 
2611   base::StackString<256> name("trusty_reclaim_mem: id=%" PRIu64, evt.id());
2612   StringId name_generic = context_->storage->InternString(name.string_view());
2613 
2614   context_->slice_tracker->Begin(timestamp, track, trusty_category_id_,
2615                                  name_generic);
2616 }
2617 
ParseTrustyReclaimMemoryDone(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2618 void FtraceParser::ParseTrustyReclaimMemoryDone(uint32_t pid,
2619                                                 int64_t timestamp,
2620                                                 protozero::ConstBytes blob) {
2621   protos::pbzero::TrustyReclaimMemoryDoneFtraceEvent::Decoder evt(blob.data,
2622                                                                   blob.size);
2623 
2624   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2625   TrackId track = context_->track_tracker->InternThreadTrack(utid);
2626   context_->slice_tracker->End(timestamp, track, trusty_category_id_);
2627 
2628   if (evt.ret() < 0) {
2629     base::StackString<256> name("trusty_reclaim_mem_err: err= %" PRIi32,
2630                                 evt.ret());
2631     StringId name_generic = context_->storage->InternString(name.string_view());
2632     context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2633                                     name_generic, 0);
2634   }
2635 }
2636 
ParseTrustyIrq(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2637 void FtraceParser::ParseTrustyIrq(uint32_t pid,
2638                                   int64_t timestamp,
2639                                   protozero::ConstBytes blob) {
2640   protos::pbzero::TrustyIrqFtraceEvent::Decoder evt(blob.data, blob.size);
2641 
2642   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2643   TrackId track = context_->track_tracker->InternThreadTrack(utid);
2644 
2645   base::StackString<256> name("trusty_irq: irq= %" PRIi32, evt.irq());
2646   StringId name_generic = context_->storage->InternString(name.string_view());
2647 
2648   context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2649                                   name_generic, 0);
2650 }
2651 
ParseTrustyIpcHandleEvent(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2652 void FtraceParser::ParseTrustyIpcHandleEvent(uint32_t pid,
2653                                              int64_t timestamp,
2654                                              protozero::ConstBytes blob) {
2655   protos::pbzero::TrustyIpcHandleEventFtraceEvent::Decoder evt(blob.data,
2656                                                                blob.size);
2657 
2658   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2659   TrackId track = context_->track_tracker->InternThreadTrack(utid);
2660 
2661   base::StackString<256> name(
2662       "trusty_ipc_handle_event: chan=%" PRIu32 " srv_name=%s event=%" PRIu32,
2663       evt.chan(), evt.srv_name().ToStdString().c_str(), evt.event_id());
2664   StringId name_generic = context_->storage->InternString(name.string_view());
2665 
2666   context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2667                                   name_generic, 0);
2668 }
2669 
ParseTrustyEnqueueNop(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2670 void FtraceParser::ParseTrustyEnqueueNop(uint32_t pid,
2671                                          int64_t timestamp,
2672                                          protozero::ConstBytes blob) {
2673   protos::pbzero::TrustyEnqueueNopFtraceEvent::Decoder evt(blob.data,
2674                                                            blob.size);
2675 
2676   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2677   TrackId track = context_->track_tracker->InternThreadTrack(utid);
2678 
2679   base::StackString<256> name("trusty_enqueue_nop: arg1= %" PRIu32
2680                               " arg2= %" PRIu32 " arg3=%" PRIu32,
2681                               evt.arg1(), evt.arg2(), evt.arg3());
2682   StringId name_generic = context_->storage->InternString(name.string_view());
2683   context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2684                                   name_generic, 0);
2685 }
2686 
ParseTrustyIpcConnect(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2687 void FtraceParser::ParseTrustyIpcConnect(uint32_t pid,
2688                                          int64_t timestamp,
2689                                          protozero::ConstBytes blob) {
2690   protos::pbzero::TrustyIpcConnectFtraceEvent::Decoder evt(blob.data,
2691                                                            blob.size);
2692 
2693   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2694   TrackId track = context_->track_tracker->InternThreadTrack(utid);
2695 
2696   base::StackString<256> name("tipc_connect: %s",
2697                               evt.port().ToStdString().c_str());
2698   StringId name_generic = context_->storage->InternString(name.string_view());
2699 
2700   context_->slice_tracker->Begin(timestamp, track, trusty_category_id_,
2701                                  name_generic);
2702 }
2703 
ParseTrustyIpcConnectEnd(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2704 void FtraceParser::ParseTrustyIpcConnectEnd(uint32_t pid,
2705                                             int64_t timestamp,
2706                                             protozero::ConstBytes blob) {
2707   protos::pbzero::TrustyIpcConnectEndFtraceEvent::Decoder evt(blob.data,
2708                                                               blob.size);
2709 
2710   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2711   TrackId track = context_->track_tracker->InternThreadTrack(utid);
2712 
2713   context_->slice_tracker->End(timestamp, track, trusty_category_id_);
2714   if (evt.err()) {
2715     base::StackString<256> name("tipc_err_connect:err= %" PRIi32, evt.err());
2716     StringId name_generic = context_->storage->InternString(name.string_view());
2717     context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2718                                     name_generic, 0);
2719   }
2720 }
2721 
ParseTrustyIpcWrite(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2722 void FtraceParser::ParseTrustyIpcWrite(uint32_t pid,
2723                                        int64_t timestamp,
2724                                        protozero::ConstBytes blob) {
2725   protos::pbzero::TrustyIpcWriteFtraceEvent::Decoder evt(blob.data, blob.size);
2726 
2727   StringId name_generic = kNullStringId;
2728   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2729   TrackId track = context_->track_tracker->InternThreadTrack(utid);
2730 
2731   if (evt.shm_cnt() > 0) {
2732     base::StackString<256> name("tipc_write: %s shm_cnt:[%" PRIu64 "]",
2733                                 evt.srv_name().ToStdString().c_str(),
2734                                 evt.shm_cnt());
2735     name_generic = context_->storage->InternString(name.string_view());
2736   } else {
2737     base::StackString<256> name("tipc_write: %s",
2738                                 evt.srv_name().ToStdString().c_str());
2739     name_generic = context_->storage->InternString(name.string_view());
2740   }
2741   context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2742                                   name_generic, 0);
2743 
2744   if (evt.len_or_err() < 0) {
2745     base::StackString<256> name("tipc_err_write:len_or_err= %" PRIi32,
2746                                 evt.len_or_err());
2747     name_generic = context_->storage->InternString(name.string_view());
2748     context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2749                                     name_generic, 0);
2750   }
2751 }
2752 
ParseTrustyIpcRead(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2753 void FtraceParser::ParseTrustyIpcRead(uint32_t pid,
2754                                       int64_t timestamp,
2755                                       protozero::ConstBytes blob) {
2756   protos::pbzero::TrustyIpcReadFtraceEvent::Decoder evt(blob.data, blob.size);
2757 
2758   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2759   TrackId track = context_->track_tracker->InternThreadTrack(utid);
2760 
2761   base::StackString<256> name("tipc_read: %s",
2762                               evt.srv_name().ToStdString().c_str());
2763   StringId name_generic = context_->storage->InternString(name.string_view());
2764   context_->slice_tracker->Begin(timestamp, track, trusty_category_id_,
2765                                  name_generic);
2766 }
2767 
ParseTrustyIpcReadEnd(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2768 void FtraceParser::ParseTrustyIpcReadEnd(uint32_t pid,
2769                                          int64_t timestamp,
2770                                          protozero::ConstBytes blob) {
2771   protos::pbzero::TrustyIpcReadEndFtraceEvent::Decoder evt(blob.data,
2772                                                            blob.size);
2773 
2774   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2775   TrackId track = context_->track_tracker->InternThreadTrack(utid);
2776   context_->slice_tracker->End(timestamp, track, trusty_category_id_);
2777 
2778   if (evt.len_or_err() <= 0) {
2779     base::StackString<256> name("tipc_err_read:len_or_err= %" PRIi32,
2780                                 evt.len_or_err());
2781     StringId name_generic = context_->storage->InternString(name.string_view());
2782     context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2783                                     name_generic, 0);
2784   }
2785 }
2786 
ParseTrustyIpcPoll(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2787 void FtraceParser::ParseTrustyIpcPoll(uint32_t pid,
2788                                       int64_t timestamp,
2789                                       protozero::ConstBytes blob) {
2790   protos::pbzero::TrustyIpcPollFtraceEvent::Decoder evt(blob.data, blob.size);
2791 
2792   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2793   TrackId track = context_->track_tracker->InternThreadTrack(utid);
2794 
2795   base::StackString<256> name("tipc_poll: %s",
2796                               evt.srv_name().ToStdString().c_str());
2797   StringId name_generic = context_->storage->InternString(name.string_view());
2798   context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2799                                   name_generic, 0);
2800 }
2801 
ParseTrustyIpcRx(uint32_t pid,int64_t ts,protozero::ConstBytes blob)2802 void FtraceParser::ParseTrustyIpcRx(uint32_t pid,
2803                                     int64_t ts,
2804                                     protozero::ConstBytes blob) {
2805   protos::pbzero::TrustyIpcRxFtraceEvent::Decoder evt(blob.data, blob.size);
2806 
2807   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2808   TrackId track = context_->track_tracker->InternThreadTrack(utid);
2809 
2810   context_->slice_tracker->Scoped(ts, track, trusty_category_id_,
2811                                   trusty_name_tipc_rx_id_, 0);
2812 }
2813 
ParseUfshcdCommand(int64_t timestamp,protozero::ConstBytes blob)2814 void FtraceParser::ParseUfshcdCommand(int64_t timestamp,
2815                                       protozero::ConstBytes blob) {
2816   protos::pbzero::UfshcdCommandFtraceEvent::Decoder evt(blob.data, blob.size);
2817 
2818   // Parse occupied ufs command queue
2819   uint32_t num = evt.doorbell() > 0
2820                      ? static_cast<uint32_t>(PERFETTO_POPCOUNT(evt.doorbell()))
2821                      : (evt.str_t() == 1 ? 0 : 1);
2822   TrackId track = context_->track_tracker->InternGlobalCounterTrack(
2823       TrackTracker::Group::kIo, ufs_command_count_id_);
2824   context_->event_tracker->PushCounter(timestamp, static_cast<double>(num),
2825                                        track);
2826 
2827   // Parse ufs command tag
2828   base::StackString<32> cmd_track_name("io.ufs.command.tag[%03d]", evt.tag());
2829   auto async_track = context_->async_track_set_tracker->InternGlobalTrackSet(
2830       context_->storage->InternString(cmd_track_name.string_view()));
2831   if (evt.str_t() == 0) {
2832     std::string ufs_op_str = GetUfsCmdString(evt.opcode(), evt.group_id());
2833     StringId ufs_slice_name =
2834         context_->storage->InternString(base::StringView(ufs_op_str));
2835     TrackId start_id = context_->async_track_set_tracker->Begin(async_track, 0);
2836     context_->slice_tracker->Begin(timestamp, start_id, kNullStringId,
2837                                    ufs_slice_name);
2838   } else {
2839     TrackId end_id = context_->async_track_set_tracker->End(async_track, 0);
2840     context_->slice_tracker->End(timestamp, end_id);
2841   }
2842 }
2843 
ParseWakeSourceActivate(int64_t timestamp,protozero::ConstBytes blob)2844 void FtraceParser::ParseWakeSourceActivate(int64_t timestamp,
2845                                            protozero::ConstBytes blob) {
2846   protos::pbzero::WakeupSourceActivateFtraceEvent::Decoder evt(blob.data,
2847                                                                blob.size);
2848   std::string event_name = evt.name().ToStdString();
2849 
2850   uint32_t count = active_wakelock_to_count_[event_name];
2851 
2852   active_wakelock_to_count_[event_name] += 1;
2853 
2854   // There is already an active track with this name, don't create another.
2855   if (count > 0) {
2856     return;
2857   }
2858 
2859   base::StackString<32> str("Wakelock(%s)", event_name.c_str());
2860   StringId stream_id = context_->storage->InternString(str.string_view());
2861 
2862   auto async_track =
2863       context_->async_track_set_tracker->InternGlobalTrackSet(stream_id);
2864 
2865   TrackId start_id = context_->async_track_set_tracker->Begin(async_track, 0);
2866 
2867   context_->slice_tracker->Begin(timestamp, start_id, kNullStringId, stream_id);
2868 }
2869 
ParseWakeSourceDeactivate(int64_t timestamp,protozero::ConstBytes blob)2870 void FtraceParser::ParseWakeSourceDeactivate(int64_t timestamp,
2871                                              protozero::ConstBytes blob) {
2872   protos::pbzero::WakeupSourceDeactivateFtraceEvent::Decoder evt(blob.data,
2873                                                                  blob.size);
2874 
2875   std::string event_name = evt.name().ToStdString();
2876   uint32_t count = active_wakelock_to_count_[event_name];
2877   active_wakelock_to_count_[event_name] = count > 0 ? count - 1 : 0;
2878   if (count != 1) {
2879     return;
2880   }
2881 
2882   base::StackString<32> str("Wakelock(%s)", event_name.c_str());
2883   StringId stream_id = context_->storage->InternString(str.string_view());
2884   auto async_track =
2885       context_->async_track_set_tracker->InternGlobalTrackSet(stream_id);
2886 
2887   TrackId end_id = context_->async_track_set_tracker->End(async_track, 0);
2888   context_->slice_tracker->End(timestamp, end_id);
2889 }
2890 
ParseSuspendResume(int64_t timestamp,protozero::ConstBytes blob)2891 void FtraceParser::ParseSuspendResume(int64_t timestamp,
2892                                       protozero::ConstBytes blob) {
2893   protos::pbzero::SuspendResumeFtraceEvent::Decoder evt(blob.data, blob.size);
2894 
2895   auto async_track = context_->async_track_set_tracker->InternGlobalTrackSet(
2896       suspend_resume_name_id_);
2897 
2898   std::string action_name = evt.action().ToStdString();
2899 
2900   // Hard code fix the timekeeping_freeze action's value to zero, the value is
2901   // processor_id and device could enter suspend/resume from different
2902   // processor.
2903   auto val = (action_name == "timekeeping_freeze") ? 0 : evt.val();
2904 
2905   base::StackString<64> str("%s(%" PRIu32 ")", action_name.c_str(), val);
2906   std::string current_action = str.ToStdString();
2907 
2908   StringId slice_name_id = context_->storage->InternString(str.string_view());
2909 
2910   if (!evt.start()) {
2911     TrackId end_id = context_->async_track_set_tracker->End(
2912         async_track, static_cast<int64_t>(val));
2913     context_->slice_tracker->End(timestamp, end_id);
2914     ongoing_suspend_resume_actions[current_action] = false;
2915     return;
2916   }
2917 
2918   // Complete the previous action before starting a new one.
2919   if (ongoing_suspend_resume_actions[current_action]) {
2920     TrackId end_id = context_->async_track_set_tracker->End(
2921         async_track, static_cast<int64_t>(val));
2922     auto args_inserter = [this](ArgsTracker::BoundInserter* inserter) {
2923       inserter->AddArg(replica_slice_id_, Variadic::Boolean(true));
2924     };
2925     context_->slice_tracker->End(timestamp, end_id, kNullStringId,
2926                                  kNullStringId, args_inserter);
2927   }
2928 
2929   TrackId start_id = context_->async_track_set_tracker->Begin(
2930       async_track, static_cast<int64_t>(val));
2931   context_->slice_tracker->Begin(timestamp, start_id, suspend_resume_name_id_,
2932                                  slice_name_id);
2933   ongoing_suspend_resume_actions[current_action] = true;
2934 }
2935 
ParseSuspendResumeMinimal(int64_t timestamp,protozero::ConstBytes blob)2936 void FtraceParser::ParseSuspendResumeMinimal(int64_t timestamp,
2937                                              protozero::ConstBytes blob) {
2938   protos::pbzero::SuspendResumeMinimalFtraceEvent::Decoder evt(blob.data,
2939                                                                blob.size);
2940   auto async_track = context_->async_track_set_tracker->InternGlobalTrackSet(
2941       suspend_resume_minimal_name_id_);
2942 
2943   if (evt.start()) {
2944     TrackId start_id = context_->async_track_set_tracker->Begin(
2945         async_track, static_cast<int64_t>(0));
2946     context_->slice_tracker->Begin(timestamp, start_id,
2947                                    suspend_resume_minimal_name_id_,
2948                                    suspend_resume_minimal_slice_name_id_);
2949   } else {
2950     TrackId end_id = context_->async_track_set_tracker->End(
2951         async_track, static_cast<int64_t>(0));
2952     context_->slice_tracker->End(timestamp, end_id);
2953   }
2954 }
2955 
ParseSchedCpuUtilCfs(int64_t timestamp,protozero::ConstBytes blob)2956 void FtraceParser::ParseSchedCpuUtilCfs(int64_t timestamp,
2957                                         protozero::ConstBytes blob) {
2958   protos::pbzero::SchedCpuUtilCfsFtraceEvent::Decoder evt(blob.data, blob.size);
2959   base::StackString<255> util_track_name("Cpu %" PRIu32 " Util", evt.cpu());
2960   StringId util_track_name_id =
2961       context_->storage->InternString(util_track_name.string_view());
2962 
2963   TrackId util_track = context_->track_tracker->InternCpuCounterTrack(
2964       util_track_name_id, evt.cpu());
2965   context_->event_tracker->PushCounter(
2966       timestamp, static_cast<double>(evt.cpu_util()), util_track);
2967 
2968   base::StackString<255> cap_track_name("Cpu %" PRIu32 " Cap", evt.cpu());
2969   StringId cap_track_name_id =
2970       context_->storage->InternString(cap_track_name.string_view());
2971 
2972   TrackId cap_track = context_->track_tracker->InternCpuCounterTrack(
2973       cap_track_name_id, evt.cpu());
2974   context_->event_tracker->PushCounter(
2975       timestamp, static_cast<double>(evt.capacity()), cap_track);
2976 
2977   base::StackString<255> nrr_track_name("Cpu %" PRIu32 " Nr Running",
2978                                         evt.cpu());
2979   StringId nrr_track_name_id =
2980       context_->storage->InternString(nrr_track_name.string_view());
2981 
2982   TrackId nrr_track = context_->track_tracker->InternCpuCounterTrack(
2983       nrr_track_name_id, evt.cpu());
2984   context_->event_tracker->PushCounter(
2985       timestamp, static_cast<double>(evt.nr_running()), nrr_track);
2986 }
2987 
ParseFuncgraphEntry(int64_t timestamp,uint32_t pid,protozero::ConstBytes blob,PacketSequenceStateGeneration * seq_state)2988 void FtraceParser::ParseFuncgraphEntry(
2989     int64_t timestamp,
2990     uint32_t pid,
2991     protozero::ConstBytes blob,
2992     PacketSequenceStateGeneration* seq_state) {
2993   // TODO(rsavitski): remove if/when we stop collapsing all idle (swapper)
2994   // threads to a single track, otherwise this breaks slice nesting.
2995   if (pid == 0)
2996     return;
2997 
2998   protos::pbzero::FuncgraphEntryFtraceEvent::Decoder evt(blob.data, blob.size);
2999   StringId name_id = InternedKernelSymbolOrFallback(evt.func(), seq_state);
3000 
3001   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
3002   TrackId track = context_->track_tracker->InternThreadTrack(utid);
3003   context_->slice_tracker->Begin(timestamp, track, kNullStringId, name_id);
3004 }
3005 
ParseFuncgraphExit(int64_t timestamp,uint32_t pid,protozero::ConstBytes blob,PacketSequenceStateGeneration * seq_state)3006 void FtraceParser::ParseFuncgraphExit(
3007     int64_t timestamp,
3008     uint32_t pid,
3009     protozero::ConstBytes blob,
3010     PacketSequenceStateGeneration* seq_state) {
3011   // TODO(rsavitski): remove if/when we stop collapsing all idle (swapper)
3012   // threads to a single track, otherwise this breaks slice nesting.
3013   if (pid == 0)
3014     return;
3015 
3016   protos::pbzero::FuncgraphExitFtraceEvent::Decoder evt(blob.data, blob.size);
3017   StringId name_id = InternedKernelSymbolOrFallback(evt.func(), seq_state);
3018 
3019   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
3020   TrackId track = context_->track_tracker->InternThreadTrack(utid);
3021   context_->slice_tracker->End(timestamp, track, kNullStringId, name_id);
3022 }
3023 
InternedKernelSymbolOrFallback(uint64_t key,PacketSequenceStateGeneration * seq_state)3024 StringId FtraceParser::InternedKernelSymbolOrFallback(
3025     uint64_t key,
3026     PacketSequenceStateGeneration* seq_state) {
3027   auto* interned_string = seq_state->LookupInternedMessage<
3028       protos::pbzero::InternedData::kKernelSymbolsFieldNumber,
3029       protos::pbzero::InternedString>(key);
3030   StringId name_id;
3031   if (interned_string) {
3032     protozero::ConstBytes str = interned_string->str();
3033     name_id = context_->storage->InternString(
3034         base::StringView(reinterpret_cast<const char*>(str.data), str.size));
3035   } else {
3036     base::StackString<255> slice_name("%#" PRIx64, key);
3037     name_id = context_->storage->InternString(slice_name.string_view());
3038   }
3039   return name_id;
3040 }
3041 
3042 }  // namespace trace_processor
3043 }  // namespace perfetto
3044