• 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/protozero/proto_decoder.h"
21 #include "src/trace_processor/importers/common/args_tracker.h"
22 #include "src/trace_processor/importers/common/process_tracker.h"
23 #include "src/trace_processor/importers/ftrace/binder_tracker.h"
24 #include "src/trace_processor/importers/proto/async_track_set_tracker.h"
25 #include "src/trace_processor/importers/proto/metadata_tracker.h"
26 #include "src/trace_processor/importers/syscalls/syscall_tracker.h"
27 #include "src/trace_processor/importers/systrace/systrace_parser.h"
28 #include "src/trace_processor/storage/stats.h"
29 #include "src/trace_processor/storage/trace_storage.h"
30 #include "src/trace_processor/types/softirq_action.h"
31 #include "src/trace_processor/types/tcp_state.h"
32 
33 #include "protos/perfetto/common/gpu_counter_descriptor.pbzero.h"
34 #include "protos/perfetto/trace/ftrace/binder.pbzero.h"
35 #include "protos/perfetto/trace/ftrace/cpuhp.pbzero.h"
36 #include "protos/perfetto/trace/ftrace/cros_ec.pbzero.h"
37 #include "protos/perfetto/trace/ftrace/dmabuf_heap.pbzero.h"
38 #include "protos/perfetto/trace/ftrace/dpu.pbzero.h"
39 #include "protos/perfetto/trace/ftrace/fastrpc.pbzero.h"
40 #include "protos/perfetto/trace/ftrace/ftrace.pbzero.h"
41 #include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
42 #include "protos/perfetto/trace/ftrace/ftrace_stats.pbzero.h"
43 #include "protos/perfetto/trace/ftrace/g2d.pbzero.h"
44 #include "protos/perfetto/trace/ftrace/generic.pbzero.h"
45 #include "protos/perfetto/trace/ftrace/gpu_mem.pbzero.h"
46 #include "protos/perfetto/trace/ftrace/ion.pbzero.h"
47 #include "protos/perfetto/trace/ftrace/irq.pbzero.h"
48 #include "protos/perfetto/trace/ftrace/kmem.pbzero.h"
49 #include "protos/perfetto/trace/ftrace/lowmemorykiller.pbzero.h"
50 #include "protos/perfetto/trace/ftrace/mali.pbzero.h"
51 #include "protos/perfetto/trace/ftrace/mm_event.pbzero.h"
52 #include "protos/perfetto/trace/ftrace/net.pbzero.h"
53 #include "protos/perfetto/trace/ftrace/oom.pbzero.h"
54 #include "protos/perfetto/trace/ftrace/power.pbzero.h"
55 #include "protos/perfetto/trace/ftrace/raw_syscalls.pbzero.h"
56 #include "protos/perfetto/trace/ftrace/sched.pbzero.h"
57 #include "protos/perfetto/trace/ftrace/scm.pbzero.h"
58 #include "protos/perfetto/trace/ftrace/sde.pbzero.h"
59 #include "protos/perfetto/trace/ftrace/signal.pbzero.h"
60 #include "protos/perfetto/trace/ftrace/skb.pbzero.h"
61 #include "protos/perfetto/trace/ftrace/sock.pbzero.h"
62 #include "protos/perfetto/trace/ftrace/systrace.pbzero.h"
63 #include "protos/perfetto/trace/ftrace/task.pbzero.h"
64 #include "protos/perfetto/trace/ftrace/tcp.pbzero.h"
65 #include "protos/perfetto/trace/ftrace/thermal.pbzero.h"
66 #include "protos/perfetto/trace/ftrace/ufs.pbzero.h"
67 #include "protos/perfetto/trace/ftrace/vmscan.pbzero.h"
68 #include "protos/perfetto/trace/ftrace/workqueue.pbzero.h"
69 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
70 
71 namespace perfetto {
72 namespace trace_processor {
73 
74 namespace {
75 
76 using protozero::ConstBytes;
77 using protozero::ProtoDecoder;
78 
79 // kthreadd is the parent process for all kernel threads and always has
80 // pid == 2 on Linux and Android.
81 const uint32_t kKthreaddPid = 2;
82 const char kKthreaddName[] = "kthreadd";
83 
84 struct FtraceEventAndFieldId {
85   uint32_t event_id;
86   uint32_t field_id;
87 };
88 
89 // Contains a list of all the proto fields in ftrace events which represent
90 // kernel functions. This list is used to convert the iids in these fields to
91 // proper kernel symbols.
92 // TODO(lalitm): going through this array is O(n) on a hot-path (see
93 // ParseTypedFtraceToRaw). Consider changing this if we end up adding a lot of
94 // events here.
95 constexpr auto kKernelFunctionFields = std::array<FtraceEventAndFieldId, 3>{
96     {FtraceEventAndFieldId{
97          protos::pbzero::FtraceEvent::kSchedBlockedReasonFieldNumber,
98          protos::pbzero::SchedBlockedReasonFtraceEvent::kCallerFieldNumber},
99      FtraceEventAndFieldId{
100          protos::pbzero::FtraceEvent::kWorkqueueExecuteStartFieldNumber,
101          protos::pbzero::WorkqueueExecuteStartFtraceEvent::
102              kFunctionFieldNumber},
103      FtraceEventAndFieldId{
104          protos::pbzero::FtraceEvent::kWorkqueueQueueWorkFieldNumber,
105          protos::pbzero::WorkqueueQueueWorkFtraceEvent::kFunctionFieldNumber}}};
106 
107 }  // namespace
108 
FtraceParser(TraceProcessorContext * context)109 FtraceParser::FtraceParser(TraceProcessorContext* context)
110     : context_(context),
111       rss_stat_tracker_(context),
112       sched_wakeup_name_id_(context->storage->InternString("sched_wakeup")),
113       sched_waking_name_id_(context->storage->InternString("sched_waking")),
114       cpu_id_(context->storage->InternString("cpu")),
115       cpu_freq_name_id_(context->storage->InternString("cpufreq")),
116       gpu_freq_name_id_(context->storage->InternString("gpufreq")),
117       cpu_idle_name_id_(context->storage->InternString("cpuidle")),
118       suspend_resume_name_id_(
119           context->storage->InternString("Suspend/Resume Latency")),
120       kfree_skb_name_id_(context->storage->InternString("Kfree Skb IP Prot")),
121       ion_total_id_(context->storage->InternString("mem.ion")),
122       ion_change_id_(context->storage->InternString("mem.ion_change")),
123       ion_buffer_id_(context->storage->InternString("mem.ion_buffer")),
124       dma_heap_total_id_(context->storage->InternString("mem.dma_heap")),
125       dma_heap_change_id_(
126           context->storage->InternString("mem.dma_heap_change")),
127       dma_buffer_id_(context->storage->InternString("mem.dma_buffer")),
128       ion_total_unknown_id_(context->storage->InternString("mem.ion.unknown")),
129       ion_change_unknown_id_(
130           context->storage->InternString("mem.ion_change.unknown")),
131       signal_generate_id_(context->storage->InternString("signal_generate")),
132       signal_deliver_id_(context->storage->InternString("signal_deliver")),
133       oom_score_adj_id_(context->storage->InternString("oom_score_adj")),
134       lmk_id_(context->storage->InternString("mem.lmk")),
135       comm_name_id_(context->storage->InternString("comm")),
136       signal_name_id_(context_->storage->InternString("signal.sig")),
137       oom_kill_id_(context_->storage->InternString("mem.oom_kill")),
138       workqueue_id_(context_->storage->InternString("workqueue")),
139       irq_id_(context_->storage->InternString("irq")),
140       tcp_state_id_(context_->storage->InternString("tcp_state")),
141       tcp_event_id_(context_->storage->InternString("tcp_event")),
142       protocol_arg_id_(context_->storage->InternString("protocol")),
143       napi_gro_id_(context_->storage->InternString("napi_gro")),
144       tcp_retransmited_name_id_(
145           context_->storage->InternString("TCP Retransmit Skb")),
146       ret_arg_id_(context_->storage->InternString("ret")),
147       len_arg_id_(context->storage->InternString("len")),
148       direct_reclaim_nr_reclaimed_id_(
149           context->storage->InternString("direct_reclaim_nr_reclaimed")),
150       direct_reclaim_order_id_(
151           context->storage->InternString("direct_reclaim_order")),
152       direct_reclaim_may_writepage_id_(
153           context->storage->InternString("direct_reclaim_may_writepage")),
154       direct_reclaim_gfp_flags_id_(
155           context->storage->InternString("direct_reclaim_gfp_flags")),
156       vec_arg_id_(context->storage->InternString("vec")),
157       gpu_mem_total_name_id_(context->storage->InternString("GPU Memory")),
158       gpu_mem_total_unit_id_(context->storage->InternString(
159           std::to_string(protos::pbzero::GpuCounterDescriptor::BYTE).c_str())),
160       gpu_mem_total_global_desc_id_(context->storage->InternString(
161           "Total GPU memory used by the entire system")),
162       gpu_mem_total_proc_desc_id_(context->storage->InternString(
163           "Total GPU memory used by this process")),
164       sched_blocked_reason_id_(
165           context->storage->InternString("sched_blocked_reason")),
166       io_wait_id_(context->storage->InternString("io_wait")),
167       function_id_(context->storage->InternString("function")),
168       waker_utid_id_(context->storage->InternString("waker_utid")),
169       cros_ec_arg_num_id_(context->storage->InternString("ec_num")),
170       cros_ec_arg_ec_id_(context->storage->InternString("ec_delta")),
171       cros_ec_arg_sample_ts_id_(context->storage->InternString("sample_ts")),
172       ufs_clkgating_id_(context->storage->InternString("UFS clkgating (OFF/REQ_OFF/REQ_ON/ON)")),
173       ufs_command_count_id_(context->storage->InternString("UFS Command Count")) {
174   // Build the lookup table for the strings inside ftrace events (e.g. the
175   // name of ftrace event fields and the names of their args).
176   for (size_t i = 0; i < GetDescriptorsSize(); i++) {
177     auto* descriptor = GetMessageDescriptorForId(i);
178     if (!descriptor->name) {
179       ftrace_message_strings_.emplace_back();
180       continue;
181     }
182 
183     FtraceMessageStrings ftrace_strings;
184     ftrace_strings.message_name_id =
185         context->storage->InternString(descriptor->name);
186 
187     for (size_t fid = 0; fid <= descriptor->max_field_id; fid++) {
188       const auto& field = descriptor->fields[fid];
189       if (!field.name)
190         continue;
191       ftrace_strings.field_name_ids[fid] =
192           context->storage->InternString(field.name);
193     }
194     ftrace_message_strings_.emplace_back(ftrace_strings);
195   }
196 
197   // Array initialization causes a spurious warning due to llvm bug.
198   // See https://bugs.llvm.org/show_bug.cgi?id=21629
199   fast_rpc_delta_names_[0] =
200       context->storage->InternString("mem.fastrpc_change[ASDP]");
201   fast_rpc_delta_names_[1] =
202       context->storage->InternString("mem.fastrpc_change[MDSP]");
203   fast_rpc_delta_names_[2] =
204       context->storage->InternString("mem.fastrpc_change[SDSP]");
205   fast_rpc_delta_names_[3] =
206       context->storage->InternString("mem.fastrpc_change[CDSP]");
207   fast_rpc_total_names_[0] =
208       context->storage->InternString("mem.fastrpc[ASDP]");
209   fast_rpc_total_names_[1] =
210       context->storage->InternString("mem.fastrpc[MDSP]");
211   fast_rpc_total_names_[2] =
212       context->storage->InternString("mem.fastrpc[SDSP]");
213   fast_rpc_total_names_[3] =
214       context->storage->InternString("mem.fastrpc[CDSP]");
215 
216   mm_event_counter_names_ = {
217       {MmEventCounterNames(
218            context->storage->InternString("mem.mm.min_flt.count"),
219            context->storage->InternString("mem.mm.min_flt.max_lat"),
220            context->storage->InternString("mem.mm.min_flt.avg_lat")),
221        MmEventCounterNames(
222            context->storage->InternString("mem.mm.maj_flt.count"),
223            context->storage->InternString("mem.mm.maj_flt.max_lat"),
224            context->storage->InternString("mem.mm.maj_flt.avg_lat")),
225        MmEventCounterNames(
226            context->storage->InternString("mem.mm.read_io.count"),
227            context->storage->InternString("mem.mm.read_io.max_lat"),
228            context->storage->InternString("mem.mm.read_io.avg_lat")),
229        MmEventCounterNames(
230            context->storage->InternString("mem.mm.compaction.count"),
231            context->storage->InternString("mem.mm.compaction.max_lat"),
232            context->storage->InternString("mem.mm.compaction.avg_lat")),
233        MmEventCounterNames(
234            context->storage->InternString("mem.mm.reclaim.count"),
235            context->storage->InternString("mem.mm.reclaim.max_lat"),
236            context->storage->InternString("mem.mm.reclaim.avg_lat")),
237        MmEventCounterNames(
238            context->storage->InternString("mem.mm.swp_flt.count"),
239            context->storage->InternString("mem.mm.swp_flt.max_lat"),
240            context->storage->InternString("mem.mm.swp_flt.avg_lat")),
241        MmEventCounterNames(
242            context->storage->InternString("mem.mm.kern_alloc.count"),
243            context->storage->InternString("mem.mm.kern_alloc.max_lat"),
244            context->storage->InternString("mem.mm.kern_alloc.avg_lat"))}};
245 }
246 
ParseFtraceStats(ConstBytes blob)247 void FtraceParser::ParseFtraceStats(ConstBytes blob) {
248   protos::pbzero::FtraceStats::Decoder evt(blob.data, blob.size);
249   bool is_start =
250       evt.phase() == protos::pbzero::FtraceStats_Phase_START_OF_TRACE;
251   bool is_end = evt.phase() == protos::pbzero::FtraceStats_Phase_END_OF_TRACE;
252   if (!is_start && !is_end) {
253     PERFETTO_ELOG("Ignoring unknown ftrace stats phase %d", evt.phase());
254     return;
255   }
256   size_t phase = is_end ? 1 : 0;
257 
258   // This code relies on the fact that each ftrace_cpu_XXX_end event is
259   // just after the corresponding ftrace_cpu_XXX_begin event.
260   static_assert(
261       stats::ftrace_cpu_read_events_end - stats::ftrace_cpu_read_events_begin ==
262               1 &&
263           stats::ftrace_cpu_entries_end - stats::ftrace_cpu_entries_begin == 1,
264       "ftrace_cpu_XXX stats definition are messed up");
265 
266   auto* storage = context_->storage.get();
267   for (auto it = evt.cpu_stats(); it; ++it) {
268     protos::pbzero::FtraceCpuStats::Decoder cpu_stats(*it);
269     int cpu = static_cast<int>(cpu_stats.cpu());
270 
271     int64_t entries = static_cast<int64_t>(cpu_stats.entries());
272     int64_t overrun = static_cast<int64_t>(cpu_stats.overrun());
273     int64_t commit_overrun = static_cast<int64_t>(cpu_stats.commit_overrun());
274     int64_t bytes_read = static_cast<int64_t>(cpu_stats.bytes_read());
275     int64_t dropped_events = static_cast<int64_t>(cpu_stats.dropped_events());
276     int64_t read_events = static_cast<int64_t>(cpu_stats.read_events());
277     int64_t now_ts = static_cast<int64_t>(cpu_stats.now_ts() * 1e9);
278 
279     storage->SetIndexedStats(stats::ftrace_cpu_entries_begin + phase, cpu,
280                              entries);
281     storage->SetIndexedStats(stats::ftrace_cpu_overrun_begin + phase, cpu,
282                              overrun);
283     storage->SetIndexedStats(stats::ftrace_cpu_commit_overrun_begin + phase,
284                              cpu, commit_overrun);
285     storage->SetIndexedStats(stats::ftrace_cpu_bytes_read_begin + phase, cpu,
286                              bytes_read);
287     storage->SetIndexedStats(stats::ftrace_cpu_dropped_events_begin + phase,
288                              cpu, dropped_events);
289     storage->SetIndexedStats(stats::ftrace_cpu_read_events_begin + phase, cpu,
290                              read_events);
291     storage->SetIndexedStats(stats::ftrace_cpu_now_ts_begin + phase, cpu,
292                              now_ts);
293 
294     if (is_end) {
295       auto opt_entries_begin =
296           storage->GetIndexedStats(stats::ftrace_cpu_entries_begin, cpu);
297       if (opt_entries_begin) {
298         int64_t delta_entries = entries - opt_entries_begin.value();
299         storage->SetIndexedStats(stats::ftrace_cpu_entries_delta, cpu,
300                                  delta_entries);
301       }
302 
303       auto opt_overrun_begin =
304           storage->GetIndexedStats(stats::ftrace_cpu_overrun_begin, cpu);
305       if (opt_overrun_begin) {
306         int64_t delta_overrun = overrun - opt_overrun_begin.value();
307         storage->SetIndexedStats(stats::ftrace_cpu_overrun_delta, cpu,
308                                  delta_overrun);
309       }
310 
311       auto opt_commit_overrun_begin =
312           storage->GetIndexedStats(stats::ftrace_cpu_commit_overrun_begin, cpu);
313       if (opt_commit_overrun_begin) {
314         int64_t delta_commit_overrun =
315             commit_overrun - opt_commit_overrun_begin.value();
316         storage->SetIndexedStats(stats::ftrace_cpu_commit_overrun_delta, cpu,
317                                  delta_commit_overrun);
318       }
319 
320       auto opt_bytes_read_begin =
321           storage->GetIndexedStats(stats::ftrace_cpu_bytes_read_begin, cpu);
322       if (opt_bytes_read_begin) {
323         int64_t delta_bytes_read = bytes_read - opt_bytes_read_begin.value();
324         storage->SetIndexedStats(stats::ftrace_cpu_bytes_read_delta, cpu,
325                                  delta_bytes_read);
326       }
327 
328       auto opt_dropped_events_begin =
329           storage->GetIndexedStats(stats::ftrace_cpu_dropped_events_begin, cpu);
330       if (opt_dropped_events_begin) {
331         int64_t delta_dropped_events =
332             dropped_events - opt_dropped_events_begin.value();
333         storage->SetIndexedStats(stats::ftrace_cpu_dropped_events_delta, cpu,
334                                  delta_dropped_events);
335       }
336 
337       auto opt_read_events_begin =
338           storage->GetIndexedStats(stats::ftrace_cpu_read_events_begin, cpu);
339       if (opt_read_events_begin) {
340         int64_t delta_read_events = read_events - opt_read_events_begin.value();
341         storage->SetIndexedStats(stats::ftrace_cpu_read_events_delta, cpu,
342                                  delta_read_events);
343       }
344     }
345 
346     // oldest_event_ts can often be set to very high values, possibly because
347     // of wrapping. Ensure that we are not overflowing to avoid ubsan
348     // complaining.
349     double oldest_event_ts = cpu_stats.oldest_event_ts() * 1e9;
350     // NB: This comparison is correct only because of the >=, it would be
351     // incorrect with >. std::numeric_limits<int64_t>::max() converted to
352     // a double is the next value representable as a double that is *larger*
353     // than std::numeric_limits<int64_t>::max(). All values that are
354     // representable as doubles and < than that value are thus representable
355     // as int64_t.
356     if (oldest_event_ts >=
357         static_cast<double>(std::numeric_limits<int64_t>::max())) {
358       storage->SetIndexedStats(stats::ftrace_cpu_oldest_event_ts_begin + phase,
359                                cpu, std::numeric_limits<int64_t>::max());
360     } else {
361       storage->SetIndexedStats(stats::ftrace_cpu_oldest_event_ts_begin + phase,
362                                cpu, static_cast<int64_t>(oldest_event_ts));
363     }
364   }
365 
366   // Compute atrace + ftrace setup errors. We do two things here:
367   // 1. We add up all the errors and put the counter in the stats table (which
368   //    can hold only numerals). This will raise an orange flag in the UI.
369   // 2. We concatenate together all the errors in a string and put that in the
370   //    medatata table.
371   // Both will be reported in the 'Info & stats' page in the UI.
372   if (is_start) {
373     std::string error_str;
374     for (auto it = evt.failed_ftrace_events(); it; ++it) {
375       storage->IncrementStats(stats::ftrace_setup_errors, 1);
376       error_str += "Ftrace event failed: " + it->as_std_string() + "\n";
377     }
378     for (auto it = evt.unknown_ftrace_events(); it; ++it) {
379       storage->IncrementStats(stats::ftrace_setup_errors, 1);
380       error_str += "Ftrace event unknown: " + it->as_std_string() + "\n";
381     }
382     if (evt.atrace_errors().size > 0) {
383       storage->IncrementStats(stats::ftrace_setup_errors, 1);
384       error_str += "Atrace failures: " + evt.atrace_errors().ToStdString();
385     }
386     auto error_str_id = storage->InternString(base::StringView(error_str));
387     context_->metadata_tracker->SetMetadata(metadata::ftrace_setup_errors,
388                                             Variadic::String(error_str_id));
389   }
390 }
391 
392 PERFETTO_ALWAYS_INLINE
ParseFtraceEvent(uint32_t cpu,const TimestampedTracePiece & ttp)393 util::Status FtraceParser::ParseFtraceEvent(uint32_t cpu,
394                                             const TimestampedTracePiece& ttp) {
395   int64_t ts = ttp.timestamp;
396 
397   // On the first ftrace packet, check the metadata table for the
398   // ts of the event which is specified in the config. If it exists we can use
399   // it to filter out ftrace packets which happen earlier than it.
400   if (PERFETTO_UNLIKELY(!has_seen_first_ftrace_packet_)) {
401     DropFtraceDataBefore drop_before = context_->config.drop_ftrace_data_before;
402     switch (drop_before) {
403       case DropFtraceDataBefore::kNoDrop: {
404         drop_ftrace_data_before_ts_ = 0;
405         break;
406       }
407       case DropFtraceDataBefore::kAllDataSourcesStarted:
408       case DropFtraceDataBefore::kTracingStarted: {
409         metadata::KeyId event_key =
410             drop_before == DropFtraceDataBefore::kAllDataSourcesStarted
411                 ? metadata::all_data_source_started_ns
412                 : metadata::tracing_started_ns;
413         const auto& metadata = context_->storage->metadata_table();
414         base::Optional<uint32_t> opt_row =
415             metadata.name().IndexOf(metadata::kNames[event_key]);
416         if (opt_row) {
417           drop_ftrace_data_before_ts_ = *metadata.int_value()[*opt_row];
418         }
419         break;
420       }
421     }
422     has_seen_first_ftrace_packet_ = true;
423   }
424 
425   if (PERFETTO_UNLIKELY(ts < drop_ftrace_data_before_ts_)) {
426     context_->storage->IncrementStats(
427         stats::ftrace_packet_before_tracing_start);
428     return util::OkStatus();
429   }
430 
431   using protos::pbzero::FtraceEvent;
432   SchedEventTracker* sched_tracker = SchedEventTracker::GetOrCreate(context_);
433 
434   // Handle the (optional) alternative encoding format for sched_switch.
435   if (ttp.type == TimestampedTracePiece::Type::kInlineSchedSwitch) {
436     const auto& event = ttp.sched_switch;
437     sched_tracker->PushSchedSwitchCompact(cpu, ts, event.prev_state,
438                                           static_cast<uint32_t>(event.next_pid),
439                                           event.next_prio, event.next_comm);
440     return util::OkStatus();
441   }
442 
443   // Handle the (optional) alternative encoding format for sched_waking.
444   if (ttp.type == TimestampedTracePiece::Type::kInlineSchedWaking) {
445     const auto& event = ttp.sched_waking;
446     sched_tracker->PushSchedWakingCompact(
447         cpu, ts, static_cast<uint32_t>(event.pid), event.target_cpu, event.prio,
448         event.comm);
449     return util::OkStatus();
450   }
451 
452   PERFETTO_DCHECK(ttp.type == TimestampedTracePiece::Type::kFtraceEvent);
453   const TraceBlobView& event = ttp.ftrace_event.event;
454   PacketSequenceStateGeneration* seq_state =
455       ttp.ftrace_event.sequence_state.get();
456   ProtoDecoder decoder(event.data(), event.length());
457   uint64_t raw_pid = 0;
458   if (auto pid_field = decoder.FindField(FtraceEvent::kPidFieldNumber)) {
459     raw_pid = pid_field.as_uint64();
460   } else {
461     return util::ErrStatus("Pid field not found in ftrace packet");
462   }
463   uint32_t pid = static_cast<uint32_t>(raw_pid);
464 
465   for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
466     bool is_metadata_field = fld.id() == FtraceEvent::kPidFieldNumber ||
467                              fld.id() == FtraceEvent::kTimestampFieldNumber;
468     if (is_metadata_field)
469       continue;
470 
471     ConstBytes data = fld.as_bytes();
472     if (fld.id() == FtraceEvent::kGenericFieldNumber) {
473       ParseGenericFtrace(ts, cpu, pid, data);
474     } else if (fld.id() != FtraceEvent::kSchedSwitchFieldNumber) {
475       // sched_switch parsing populates the raw table by itself
476       ParseTypedFtraceToRaw(fld.id(), ts, cpu, pid, data, seq_state);
477     }
478 
479     switch (fld.id()) {
480       case FtraceEvent::kSchedSwitchFieldNumber: {
481         ParseSchedSwitch(cpu, ts, data);
482         break;
483       }
484       case FtraceEvent::kSchedWakeupFieldNumber: {
485         ParseSchedWakeup(ts, pid, data);
486         break;
487       }
488       case FtraceEvent::kSchedWakingFieldNumber: {
489         ParseSchedWaking(ts, pid, data);
490         break;
491       }
492       case FtraceEvent::kSchedProcessFreeFieldNumber: {
493         ParseSchedProcessFree(ts, data);
494         break;
495       }
496       case FtraceEvent::kCpuFrequencyFieldNumber: {
497         ParseCpuFreq(ts, data);
498         break;
499       }
500       case FtraceEvent::kGpuFrequencyFieldNumber: {
501         ParseGpuFreq(ts, data);
502         break;
503       }
504       case FtraceEvent::kCpuIdleFieldNumber: {
505         ParseCpuIdle(ts, data);
506         break;
507       }
508       case FtraceEvent::kPrintFieldNumber: {
509         ParsePrint(ts, pid, data);
510         break;
511       }
512       case FtraceEvent::kZeroFieldNumber: {
513         ParseZero(ts, pid, data);
514         break;
515       }
516       case FtraceEvent::kRssStatThrottledFieldNumber:
517       case FtraceEvent::kRssStatFieldNumber: {
518         rss_stat_tracker_.ParseRssStat(ts, fld.id(), pid, data);
519         break;
520       }
521       case FtraceEvent::kIonHeapGrowFieldNumber: {
522         ParseIonHeapGrowOrShrink(ts, pid, data, true);
523         break;
524       }
525       case FtraceEvent::kIonHeapShrinkFieldNumber: {
526         ParseIonHeapGrowOrShrink(ts, pid, data, false);
527         break;
528       }
529       case FtraceEvent::kIonStatFieldNumber: {
530         ParseIonStat(ts, pid, data);
531         break;
532       }
533       case FtraceEvent::kDmaHeapStatFieldNumber: {
534         ParseDmaHeapStat(ts, pid, data);
535         break;
536       }
537       case FtraceEvent::kSignalGenerateFieldNumber: {
538         ParseSignalGenerate(ts, data);
539         break;
540       }
541       case FtraceEvent::kSignalDeliverFieldNumber: {
542         ParseSignalDeliver(ts, pid, data);
543         break;
544       }
545       case FtraceEvent::kLowmemoryKillFieldNumber: {
546         ParseLowmemoryKill(ts, data);
547         break;
548       }
549       case FtraceEvent::kOomScoreAdjUpdateFieldNumber: {
550         ParseOOMScoreAdjUpdate(ts, data);
551         break;
552       }
553       case FtraceEvent::kMarkVictimFieldNumber: {
554         ParseOOMKill(ts, data);
555         break;
556       }
557       case FtraceEvent::kMmEventRecordFieldNumber: {
558         ParseMmEventRecord(ts, pid, data);
559         break;
560       }
561       case FtraceEvent::kSysEnterFieldNumber: {
562         ParseSysEvent(ts, pid, true, data);
563         break;
564       }
565       case FtraceEvent::kSysExitFieldNumber: {
566         ParseSysEvent(ts, pid, false, data);
567         break;
568       }
569       case FtraceEvent::kTaskNewtaskFieldNumber: {
570         ParseTaskNewTask(ts, pid, data);
571         break;
572       }
573       case FtraceEvent::kTaskRenameFieldNumber: {
574         ParseTaskRename(data);
575         break;
576       }
577       case FtraceEvent::kBinderTransactionFieldNumber: {
578         ParseBinderTransaction(ts, pid, data);
579         break;
580       }
581       case FtraceEvent::kBinderTransactionReceivedFieldNumber: {
582         ParseBinderTransactionReceived(ts, pid, data);
583         break;
584       }
585       case FtraceEvent::kBinderTransactionAllocBufFieldNumber: {
586         ParseBinderTransactionAllocBuf(ts, pid, data);
587         break;
588       }
589       case FtraceEvent::kBinderLockFieldNumber: {
590         ParseBinderLock(ts, pid, data);
591         break;
592       }
593       case FtraceEvent::kBinderUnlockFieldNumber: {
594         ParseBinderUnlock(ts, pid, data);
595         break;
596       }
597       case FtraceEvent::kBinderLockedFieldNumber: {
598         ParseBinderLocked(ts, pid, data);
599         break;
600       }
601       case FtraceEvent::kSdeTracingMarkWriteFieldNumber: {
602         ParseSdeTracingMarkWrite(ts, pid, data);
603         break;
604       }
605       case FtraceEvent::kClockSetRateFieldNumber: {
606         ParseClockSetRate(ts, data);
607         break;
608       }
609       case FtraceEvent::kClockEnableFieldNumber: {
610         ParseClockEnable(ts, data);
611         break;
612       }
613       case FtraceEvent::kClockDisableFieldNumber: {
614         ParseClockDisable(ts, data);
615         break;
616       }
617       case FtraceEvent::kScmCallStartFieldNumber: {
618         ParseScmCallStart(ts, pid, data);
619         break;
620       }
621       case FtraceEvent::kScmCallEndFieldNumber: {
622         ParseScmCallEnd(ts, pid, data);
623         break;
624       }
625       case FtraceEvent::kMmVmscanDirectReclaimBeginFieldNumber: {
626         ParseDirectReclaimBegin(ts, pid, data);
627         break;
628       }
629       case FtraceEvent::kMmVmscanDirectReclaimEndFieldNumber: {
630         ParseDirectReclaimEnd(ts, pid, data);
631         break;
632       }
633       case FtraceEvent::kWorkqueueExecuteStartFieldNumber: {
634         ParseWorkqueueExecuteStart(cpu, ts, pid, data, seq_state);
635         break;
636       }
637       case FtraceEvent::kWorkqueueExecuteEndFieldNumber: {
638         ParseWorkqueueExecuteEnd(ts, pid, data);
639         break;
640       }
641       case FtraceEvent::kIrqHandlerEntryFieldNumber: {
642         ParseIrqHandlerEntry(cpu, ts, data);
643         break;
644       }
645       case FtraceEvent::kIrqHandlerExitFieldNumber: {
646         ParseIrqHandlerExit(cpu, ts, data);
647         break;
648       }
649       case FtraceEvent::kSoftirqEntryFieldNumber: {
650         ParseSoftIrqEntry(cpu, ts, data);
651         break;
652       }
653       case FtraceEvent::kSoftirqExitFieldNumber: {
654         ParseSoftIrqExit(cpu, ts, data);
655         break;
656       }
657       case FtraceEvent::kGpuMemTotalFieldNumber: {
658         ParseGpuMemTotal(ts, data);
659         break;
660       }
661       case FtraceEvent::kThermalTemperatureFieldNumber: {
662         ParseThermalTemperature(ts, data);
663         break;
664       }
665       case FtraceEvent::kCdevUpdateFieldNumber: {
666         ParseCdevUpdate(ts, data);
667         break;
668       }
669       case FtraceEvent::kSchedBlockedReasonFieldNumber: {
670         ParseSchedBlockedReason(ts, data, seq_state);
671         break;
672       }
673       case FtraceEvent::kFastrpcDmaStatFieldNumber: {
674         ParseFastRpcDmaStat(ts, pid, data);
675         break;
676       }
677       case FtraceEvent::kG2dTracingMarkWriteFieldNumber: {
678         ParseG2dTracingMarkWrite(ts, pid, data);
679         break;
680       }
681       case FtraceEvent::kDpuTracingMarkWriteFieldNumber: {
682         ParseDpuTracingMarkWrite(ts, pid, data);
683         break;
684       }
685       case FtraceEvent::kMaliTracingMarkWriteFieldNumber: {
686         ParseMaliTracingMarkWrite(ts, pid, data);
687         break;
688       }
689       case FtraceEvent::kCpuhpPauseFieldNumber: {
690         ParseCpuhpPause(ts, pid, data);
691         break;
692       }
693       case FtraceEvent::kNetifReceiveSkbFieldNumber: {
694         ParseNetifReceiveSkb(cpu, ts, data);
695         break;
696       }
697       case FtraceEvent::kNetDevXmitFieldNumber: {
698         ParseNetDevXmit(cpu, ts, data);
699         break;
700       }
701       case FtraceEvent::kInetSockSetStateFieldNumber: {
702         ParseInetSockSetState(ts, pid, data);
703         break;
704       }
705       case FtraceEvent::kTcpRetransmitSkbFieldNumber: {
706         ParseTcpRetransmitSkb(ts, data);
707         break;
708       }
709       case FtraceEvent::kNapiGroReceiveEntryFieldNumber: {
710         ParseNapiGroReceiveEntry(cpu, ts, data);
711         break;
712       }
713       case FtraceEvent::kNapiGroReceiveExitFieldNumber: {
714         ParseNapiGroReceiveExit(cpu, ts, data);
715         break;
716       }
717       case FtraceEvent::kCpuFrequencyLimitsFieldNumber: {
718         ParseCpuFrequencyLimits(ts, data);
719         break;
720       }
721       case FtraceEvent::kKfreeSkbFieldNumber: {
722         ParseKfreeSkb(ts, data);
723         break;
724       }
725       case FtraceEvent::kCrosEcSensorhubDataFieldNumber: {
726         ParseCrosEcSensorhubData(ts, data);
727         break;
728       }
729       case FtraceEvent::kUfshcdCommandFieldNumber: {
730         ParseUfshcdCommand(ts, data);
731         break;
732       }
733       case FtraceEvent::kWakeupSourceActivateFieldNumber: {
734         ParseWakeSourceActivate(ts, data);
735         break;
736       }
737       case FtraceEvent::kWakeupSourceDeactivateFieldNumber: {
738         ParseWakeSourceDeactivate(ts, data);
739         break;
740       }
741       case FtraceEvent::kUfshcdClkGatingFieldNumber: {
742         ParseUfshcdClkGating(ts, data);
743         break;
744       }
745       case FtraceEvent::kSuspendResumeFieldNumber: {
746         ParseSuspendResume(ts, data);
747         break;
748       }
749       default:
750         break;
751     }
752   }
753 
754   PERFETTO_DCHECK(!decoder.bytes_left());
755   return util::OkStatus();
756 }
757 
ParseGenericFtrace(int64_t ts,uint32_t cpu,uint32_t tid,ConstBytes blob)758 void FtraceParser::ParseGenericFtrace(int64_t ts,
759                                       uint32_t cpu,
760                                       uint32_t tid,
761                                       ConstBytes blob) {
762   protos::pbzero::GenericFtraceEvent::Decoder evt(blob.data, blob.size);
763   StringId event_id = context_->storage->InternString(evt.event_name());
764   UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
765   RawId id = context_->storage->mutable_raw_table()
766                  ->Insert({ts, event_id, cpu, utid})
767                  .id;
768   auto inserter = context_->args_tracker->AddArgsTo(id);
769 
770   for (auto it = evt.field(); it; ++it) {
771     protos::pbzero::GenericFtraceEvent::Field::Decoder fld(*it);
772     auto field_name_id = context_->storage->InternString(fld.name());
773     if (fld.has_int_value()) {
774       inserter.AddArg(field_name_id, Variadic::Integer(fld.int_value()));
775     } else if (fld.has_uint_value()) {
776       inserter.AddArg(
777           field_name_id,
778           Variadic::Integer(static_cast<int64_t>(fld.uint_value())));
779     } else if (fld.has_str_value()) {
780       StringId str_value = context_->storage->InternString(fld.str_value());
781       inserter.AddArg(field_name_id, Variadic::String(str_value));
782     }
783   }
784 }
785 
ParseTypedFtraceToRaw(uint32_t ftrace_id,int64_t timestamp,uint32_t cpu,uint32_t tid,ConstBytes blob,PacketSequenceStateGeneration * seq_state)786 void FtraceParser::ParseTypedFtraceToRaw(
787     uint32_t ftrace_id,
788     int64_t timestamp,
789     uint32_t cpu,
790     uint32_t tid,
791     ConstBytes blob,
792     PacketSequenceStateGeneration* seq_state) {
793   if (PERFETTO_UNLIKELY(!context_->config.ingest_ftrace_in_raw_table))
794     return;
795 
796   ProtoDecoder decoder(blob.data, blob.size);
797   if (ftrace_id >= GetDescriptorsSize()) {
798     PERFETTO_DLOG("Event with id: %d does not exist and cannot be parsed.",
799                   ftrace_id);
800     return;
801   }
802 
803   MessageDescriptor* m = GetMessageDescriptorForId(ftrace_id);
804   const auto& message_strings = ftrace_message_strings_[ftrace_id];
805   UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
806   RawId id =
807       context_->storage->mutable_raw_table()
808           ->Insert({timestamp, message_strings.message_name_id, cpu, utid})
809           .id;
810   auto inserter = context_->args_tracker->AddArgsTo(id);
811 
812   for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
813     uint16_t field_id = fld.id();
814     if (PERFETTO_UNLIKELY(field_id >= kMaxFtraceEventFields)) {
815       PERFETTO_DLOG(
816           "Skipping ftrace arg - proto field id is too large (%" PRIu16 ")",
817           field_id);
818       continue;
819     }
820 
821     ProtoSchemaType type = m->fields[field_id].type;
822     StringId name_id = message_strings.field_name_ids[field_id];
823 
824     // Check if this field represents a kernel function.
825     auto it = std::find_if(
826         kKernelFunctionFields.begin(), kKernelFunctionFields.end(),
827         [ftrace_id, field_id](const FtraceEventAndFieldId& ev) {
828           return ev.event_id == ftrace_id && ev.field_id == field_id;
829         });
830     if (it != kKernelFunctionFields.end()) {
831       PERFETTO_CHECK(type == ProtoSchemaType::kUint64);
832 
833       auto* interned_string = seq_state->LookupInternedMessage<
834           protos::pbzero::InternedData::kKernelSymbolsFieldNumber,
835           protos::pbzero::InternedString>(fld.as_uint64());
836 
837       // If we don't have the string for this field (can happen if
838       // symbolization wasn't enabled, if reading the symbols errored out or
839       // on legacy traces) then just add the field as a normal arg.
840       if (interned_string) {
841         protozero::ConstBytes str = interned_string->str();
842         StringId str_id = context_->storage->InternString(base::StringView(
843             reinterpret_cast<const char*>(str.data), str.size));
844         inserter.AddArg(name_id, Variadic::String(str_id));
845         continue;
846       }
847     }
848 
849     switch (type) {
850       case ProtoSchemaType::kInt32:
851       case ProtoSchemaType::kInt64:
852       case ProtoSchemaType::kSfixed32:
853       case ProtoSchemaType::kSfixed64:
854       case ProtoSchemaType::kSint32:
855       case ProtoSchemaType::kSint64:
856       case ProtoSchemaType::kBool:
857       case ProtoSchemaType::kEnum: {
858         inserter.AddArg(name_id, Variadic::Integer(fld.as_int64()));
859         break;
860       }
861       case ProtoSchemaType::kUint32:
862       case ProtoSchemaType::kUint64:
863       case ProtoSchemaType::kFixed32:
864       case ProtoSchemaType::kFixed64: {
865         // Note that SQLite functions will still treat unsigned values
866         // as a signed 64 bit integers (but the translation back to ftrace
867         // refers to this storage directly).
868         inserter.AddArg(name_id, Variadic::UnsignedInteger(fld.as_uint64()));
869         break;
870       }
871       case ProtoSchemaType::kString:
872       case ProtoSchemaType::kBytes: {
873         StringId value = context_->storage->InternString(fld.as_string());
874         inserter.AddArg(name_id, Variadic::String(value));
875         break;
876       }
877       case ProtoSchemaType::kDouble: {
878         inserter.AddArg(name_id, Variadic::Real(fld.as_double()));
879         break;
880       }
881       case ProtoSchemaType::kFloat: {
882         inserter.AddArg(name_id,
883                         Variadic::Real(static_cast<double>(fld.as_float())));
884         break;
885       }
886       case ProtoSchemaType::kUnknown:
887       case ProtoSchemaType::kGroup:
888       case ProtoSchemaType::kMessage:
889         PERFETTO_DLOG("Could not store %s as a field in args table.",
890                       ProtoSchemaToString(type));
891         break;
892     }
893   }
894 }
895 
896 PERFETTO_ALWAYS_INLINE
ParseSchedSwitch(uint32_t cpu,int64_t timestamp,ConstBytes blob)897 void FtraceParser::ParseSchedSwitch(uint32_t cpu,
898                                     int64_t timestamp,
899                                     ConstBytes blob) {
900   protos::pbzero::SchedSwitchFtraceEvent::Decoder ss(blob.data, blob.size);
901   uint32_t prev_pid = static_cast<uint32_t>(ss.prev_pid());
902   uint32_t next_pid = static_cast<uint32_t>(ss.next_pid());
903   SchedEventTracker::GetOrCreate(context_)->PushSchedSwitch(
904       cpu, timestamp, prev_pid, ss.prev_comm(), ss.prev_prio(), ss.prev_state(),
905       next_pid, ss.next_comm(), ss.next_prio());
906 }
907 
ParseSchedWakeup(int64_t timestamp,uint32_t pid,ConstBytes blob)908 void FtraceParser::ParseSchedWakeup(int64_t timestamp,
909                                     uint32_t pid,
910                                     ConstBytes blob) {
911   protos::pbzero::SchedWakeupFtraceEvent::Decoder sw(blob.data, blob.size);
912   uint32_t wakee_pid = static_cast<uint32_t>(sw.pid());
913   StringId name_id = context_->storage->InternString(sw.comm());
914   auto wakee_utid = context_->process_tracker->UpdateThreadName(
915       wakee_pid, name_id, ThreadNamePriority::kFtrace);
916   InstantId id = context_->event_tracker->PushInstant(
917       timestamp, sched_wakeup_name_id_, wakee_utid, RefType::kRefUtid);
918 
919   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
920   context_->args_tracker->AddArgsTo(id).AddArg(waker_utid_id_,
921                                                Variadic::UnsignedInteger(utid));
922 }
923 
ParseSchedWaking(int64_t timestamp,uint32_t pid,ConstBytes blob)924 void FtraceParser::ParseSchedWaking(int64_t timestamp,
925                                     uint32_t pid,
926                                     ConstBytes blob) {
927   protos::pbzero::SchedWakingFtraceEvent::Decoder sw(blob.data, blob.size);
928   uint32_t wakee_pid = static_cast<uint32_t>(sw.pid());
929   StringId name_id = context_->storage->InternString(sw.comm());
930   auto wakee_utid = context_->process_tracker->UpdateThreadName(
931       wakee_pid, name_id, ThreadNamePriority::kFtrace);
932   InstantId id = context_->event_tracker->PushInstant(
933       timestamp, sched_waking_name_id_, wakee_utid, RefType::kRefUtid);
934 
935   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
936   context_->args_tracker->AddArgsTo(id).AddArg(waker_utid_id_,
937                                                Variadic::UnsignedInteger(utid));
938 }
939 
ParseSchedProcessFree(int64_t timestamp,ConstBytes blob)940 void FtraceParser::ParseSchedProcessFree(int64_t timestamp, ConstBytes blob) {
941   protos::pbzero::SchedProcessFreeFtraceEvent::Decoder ex(blob.data, blob.size);
942   uint32_t pid = static_cast<uint32_t>(ex.pid());
943   context_->process_tracker->EndThread(timestamp, pid);
944 }
945 
ParseCpuFreq(int64_t timestamp,ConstBytes blob)946 void FtraceParser::ParseCpuFreq(int64_t timestamp, ConstBytes blob) {
947   protos::pbzero::CpuFrequencyFtraceEvent::Decoder freq(blob.data, blob.size);
948   uint32_t cpu = freq.cpu_id();
949   uint32_t new_freq = freq.state();
950   TrackId track =
951       context_->track_tracker->InternCpuCounterTrack(cpu_freq_name_id_, cpu);
952   context_->event_tracker->PushCounter(timestamp, new_freq, track);
953 }
954 
ParseGpuFreq(int64_t timestamp,ConstBytes blob)955 void FtraceParser::ParseGpuFreq(int64_t timestamp, ConstBytes blob) {
956   protos::pbzero::GpuFrequencyFtraceEvent::Decoder freq(blob.data, blob.size);
957   uint32_t gpu = freq.gpu_id();
958   uint32_t new_freq = freq.state();
959   TrackId track =
960       context_->track_tracker->InternGpuCounterTrack(gpu_freq_name_id_, gpu);
961   context_->event_tracker->PushCounter(timestamp, new_freq, track);
962 }
963 
ParseCpuIdle(int64_t timestamp,ConstBytes blob)964 void FtraceParser::ParseCpuIdle(int64_t timestamp, ConstBytes blob) {
965   protos::pbzero::CpuIdleFtraceEvent::Decoder idle(blob.data, blob.size);
966   uint32_t cpu = idle.cpu_id();
967   uint32_t new_state = idle.state();
968   TrackId track =
969       context_->track_tracker->InternCpuCounterTrack(cpu_idle_name_id_, cpu);
970   context_->event_tracker->PushCounter(timestamp, new_state, track);
971 }
972 
ParsePrint(int64_t timestamp,uint32_t pid,ConstBytes blob)973 void FtraceParser::ParsePrint(int64_t timestamp,
974                               uint32_t pid,
975                               ConstBytes blob) {
976   protos::pbzero::PrintFtraceEvent::Decoder evt(blob.data, blob.size);
977   SystraceParser::GetOrCreate(context_)->ParsePrintEvent(timestamp, pid,
978                                                          evt.buf());
979 }
980 
ParseZero(int64_t timestamp,uint32_t pid,ConstBytes blob)981 void FtraceParser::ParseZero(int64_t timestamp, uint32_t pid, ConstBytes blob) {
982   protos::pbzero::ZeroFtraceEvent::Decoder evt(blob.data, blob.size);
983   uint32_t tgid = static_cast<uint32_t>(evt.pid());
984   SystraceParser::GetOrCreate(context_)->ParseZeroEvent(
985       timestamp, pid, evt.flag(), evt.name(), tgid, evt.value());
986 }
987 
ParseSdeTracingMarkWrite(int64_t timestamp,uint32_t pid,ConstBytes blob)988 void FtraceParser::ParseSdeTracingMarkWrite(int64_t timestamp,
989                                             uint32_t pid,
990                                             ConstBytes blob) {
991   protos::pbzero::SdeTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
992                                                               blob.size);
993   if (!evt.has_trace_type() && !evt.has_trace_begin()) {
994     context_->storage->IncrementStats(stats::systrace_parse_failure);
995     return;
996   }
997 
998   uint32_t tgid = static_cast<uint32_t>(evt.pid());
999   SystraceParser::GetOrCreate(context_)->ParseTracingMarkWrite(
1000       timestamp, pid, static_cast<char>(evt.trace_type()), evt.trace_begin(),
1001       evt.trace_name(), tgid, evt.value());
1002 }
1003 
ParseDpuTracingMarkWrite(int64_t timestamp,uint32_t pid,ConstBytes blob)1004 void FtraceParser::ParseDpuTracingMarkWrite(int64_t timestamp,
1005                                             uint32_t pid,
1006                                             ConstBytes blob) {
1007   protos::pbzero::DpuTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
1008                                                               blob.size);
1009   if (!evt.type()) {
1010     context_->storage->IncrementStats(stats::systrace_parse_failure);
1011     return;
1012   }
1013 
1014   uint32_t tgid = static_cast<uint32_t>(evt.pid());
1015   // For kernel counter events, they will become thread counter tracks.
1016   // But, we want to use the pid field specified in the event as the thread ID
1017   // of the thread_counter_track instead of using the thread ID that emitted
1018   // the events. So here, we need to override pid = tgid.
1019   if (static_cast<char>(evt.type()) == 'C') {
1020     pid = tgid;
1021   }
1022   SystraceParser::GetOrCreate(context_)->ParseTracingMarkWrite(
1023       timestamp, pid, static_cast<char>(evt.type()), false /*trace_begin*/,
1024       evt.name(), tgid, evt.value());
1025 }
1026 
ParseG2dTracingMarkWrite(int64_t timestamp,uint32_t pid,ConstBytes blob)1027 void FtraceParser::ParseG2dTracingMarkWrite(int64_t timestamp,
1028                                             uint32_t pid,
1029                                             ConstBytes blob) {
1030   protos::pbzero::G2dTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
1031                                                               blob.size);
1032   if (!evt.type()) {
1033     context_->storage->IncrementStats(stats::systrace_parse_failure);
1034     return;
1035   }
1036 
1037   uint32_t tgid = static_cast<uint32_t>(evt.pid());
1038   // For kernel counter events, they will become thread counter tracks.
1039   // But, we want to use the pid field specified in the event as the thread ID
1040   // of the thread_counter_track instead of using the thread ID that emitted
1041   // the events. So here, we need to override pid = tgid.
1042   if (static_cast<char>(evt.type()) == 'C') {
1043     pid = tgid;
1044   }
1045   SystraceParser::GetOrCreate(context_)->ParseTracingMarkWrite(
1046       timestamp, pid, static_cast<char>(evt.type()), false /*trace_begin*/,
1047       evt.name(), tgid, evt.value());
1048 }
1049 
ParseMaliTracingMarkWrite(int64_t timestamp,uint32_t pid,ConstBytes blob)1050 void FtraceParser::ParseMaliTracingMarkWrite(int64_t timestamp,
1051                                              uint32_t pid,
1052                                              ConstBytes blob) {
1053   protos::pbzero::MaliTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
1054                                                                blob.size);
1055   if (!evt.type()) {
1056     context_->storage->IncrementStats(stats::systrace_parse_failure);
1057     return;
1058   }
1059 
1060   uint32_t tgid = static_cast<uint32_t>(evt.pid());
1061   SystraceParser::GetOrCreate(context_)->ParseTracingMarkWrite(
1062       timestamp, pid, static_cast<char>(evt.type()), false /*trace_begin*/,
1063       evt.name(), tgid, evt.value());
1064 }
1065 
1066 /** Parses ion heap events present in Pixel kernels. */
ParseIonHeapGrowOrShrink(int64_t timestamp,uint32_t pid,ConstBytes blob,bool grow)1067 void FtraceParser::ParseIonHeapGrowOrShrink(int64_t timestamp,
1068                                             uint32_t pid,
1069                                             ConstBytes blob,
1070                                             bool grow) {
1071   protos::pbzero::IonHeapGrowFtraceEvent::Decoder ion(blob.data, blob.size);
1072   int64_t change_bytes = static_cast<int64_t>(ion.len()) * (grow ? 1 : -1);
1073   // The total_allocated ftrace event reports the value before the
1074   // atomic_long_add / sub takes place.
1075   int64_t total_bytes = ion.total_allocated() + change_bytes;
1076   StringId global_name_id = ion_total_unknown_id_;
1077   StringId change_name_id = ion_change_unknown_id_;
1078 
1079   if (ion.has_heap_name()) {
1080     base::StringView heap_name = ion.heap_name();
1081     base::StackString<255> ion_name("mem.ion.%.*s", int(heap_name.size()),
1082                                     heap_name.data());
1083     global_name_id = context_->storage->InternString(ion_name.string_view());
1084 
1085     base::StackString<255> change_name("mem.ion_change.%.*s",
1086                                        int(heap_name.size()), heap_name.data());
1087     change_name_id = context_->storage->InternString(change_name.string_view());
1088   }
1089 
1090   // Push the global counter.
1091   TrackId track =
1092       context_->track_tracker->InternGlobalCounterTrack(global_name_id);
1093   context_->event_tracker->PushCounter(timestamp,
1094                                        static_cast<double>(total_bytes), track);
1095 
1096   // Push the change counter.
1097   // TODO(b/121331269): these should really be instant events.
1098   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1099   track =
1100       context_->track_tracker->InternThreadCounterTrack(change_name_id, utid);
1101   context_->event_tracker->PushCounter(
1102       timestamp, static_cast<double>(change_bytes), track);
1103 
1104   // We are reusing the same function for ion_heap_grow and ion_heap_shrink.
1105   // It is fine as the arguments are the same, but we need to be sure that the
1106   // protobuf field id for both are the same.
1107   static_assert(
1108       static_cast<int>(
1109           protos::pbzero::IonHeapGrowFtraceEvent::kTotalAllocatedFieldNumber) ==
1110               static_cast<int>(protos::pbzero::IonHeapShrinkFtraceEvent::
1111                                    kTotalAllocatedFieldNumber) &&
1112           static_cast<int>(
1113               protos::pbzero::IonHeapGrowFtraceEvent::kLenFieldNumber) ==
1114               static_cast<int>(
1115                   protos::pbzero::IonHeapShrinkFtraceEvent::kLenFieldNumber) &&
1116           static_cast<int>(
1117               protos::pbzero::IonHeapGrowFtraceEvent::kHeapNameFieldNumber) ==
1118               static_cast<int>(protos::pbzero::IonHeapShrinkFtraceEvent::
1119                                    kHeapNameFieldNumber),
1120       "ION field mismatch");
1121 }
1122 
1123 /** Parses ion heap events (introduced in 4.19 kernels). */
ParseIonStat(int64_t timestamp,uint32_t pid,protozero::ConstBytes data)1124 void FtraceParser::ParseIonStat(int64_t timestamp,
1125                                 uint32_t pid,
1126                                 protozero::ConstBytes data) {
1127   protos::pbzero::IonStatFtraceEvent::Decoder ion(data.data, data.size);
1128   // Push the global counter.
1129   TrackId track =
1130       context_->track_tracker->InternGlobalCounterTrack(ion_total_id_);
1131   context_->event_tracker->PushCounter(
1132       timestamp, static_cast<double>(ion.total_allocated()), track);
1133 
1134   // Push the change counter.
1135   // TODO(b/121331269): these should really be instant events.
1136   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1137   track =
1138       context_->track_tracker->InternThreadCounterTrack(ion_change_id_, utid);
1139   context_->event_tracker->PushCounter(timestamp,
1140                                        static_cast<double>(ion.len()), track);
1141 
1142   // Global track for individual buffer tracking
1143   auto async_track =
1144       context_->async_track_set_tracker->InternGlobalTrackSet(ion_buffer_id_);
1145   if (ion.len() > 0) {
1146     TrackId start_id =
1147         context_->async_track_set_tracker->Begin(async_track, ion.buffer_id());
1148     std::string buf = std::to_string(ion.len() / 1024) + " kB";
1149     context_->slice_tracker->Begin(
1150         timestamp, start_id, kNullStringId,
1151         context_->storage->InternString(base::StringView(buf)));
1152   } else {
1153     TrackId end_id =
1154         context_->async_track_set_tracker->End(async_track, ion.buffer_id());
1155     context_->slice_tracker->End(timestamp, end_id);
1156   }
1157 }
1158 
ParseDmaHeapStat(int64_t timestamp,uint32_t pid,protozero::ConstBytes data)1159 void FtraceParser::ParseDmaHeapStat(int64_t timestamp,
1160                                     uint32_t pid,
1161                                     protozero::ConstBytes data) {
1162   protos::pbzero::DmaHeapStatFtraceEvent::Decoder dma_heap(data.data,
1163                                                            data.size);
1164   // Push the global counter.
1165   TrackId track =
1166       context_->track_tracker->InternGlobalCounterTrack(dma_heap_total_id_);
1167   context_->event_tracker->PushCounter(
1168       timestamp, static_cast<double>(dma_heap.total_allocated()), track);
1169 
1170   // Push the change counter.
1171   // TODO(b/121331269): these should really be instant events.
1172   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1173   track = context_->track_tracker->InternThreadCounterTrack(dma_heap_change_id_,
1174                                                             utid);
1175   context_->event_tracker->PushCounter(
1176       timestamp, static_cast<double>(dma_heap.len()), track);
1177 
1178   // Global track for individual buffer tracking
1179   auto async_track =
1180       context_->async_track_set_tracker->InternGlobalTrackSet(dma_buffer_id_);
1181   if (dma_heap.len() > 0) {
1182     TrackId start_id = context_->async_track_set_tracker->Begin(
1183         async_track, static_cast<int64_t>(dma_heap.inode()));
1184     std::string buf = std::to_string(dma_heap.len() / 1024) + " kB";
1185     context_->slice_tracker->Begin(
1186         timestamp, start_id, kNullStringId,
1187         context_->storage->InternString(base::StringView(buf)));
1188   } else {
1189     TrackId end_id = context_->async_track_set_tracker->End(
1190         async_track, static_cast<int64_t>(dma_heap.inode()));
1191     context_->slice_tracker->End(timestamp, end_id);
1192   }
1193 }
1194 
1195 // This event has both the pid of the thread that sent the signal and the
1196 // destination of the signal. Currently storing the pid of the destination.
ParseSignalGenerate(int64_t timestamp,ConstBytes blob)1197 void FtraceParser::ParseSignalGenerate(int64_t timestamp, ConstBytes blob) {
1198   protos::pbzero::SignalGenerateFtraceEvent::Decoder sig(blob.data, blob.size);
1199 
1200   UniqueTid utid = context_->process_tracker->GetOrCreateThread(
1201       static_cast<uint32_t>(sig.pid()));
1202   InstantId id = context_->event_tracker->PushInstant(
1203       timestamp, signal_generate_id_, utid, RefType::kRefUtid);
1204 
1205   context_->args_tracker->AddArgsTo(id).AddArg(signal_name_id_,
1206                                                Variadic::Integer(sig.sig()));
1207 }
1208 
ParseSignalDeliver(int64_t timestamp,uint32_t pid,ConstBytes blob)1209 void FtraceParser::ParseSignalDeliver(int64_t timestamp,
1210                                       uint32_t pid,
1211                                       ConstBytes blob) {
1212   protos::pbzero::SignalDeliverFtraceEvent::Decoder sig(blob.data, blob.size);
1213   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1214   InstantId id = context_->event_tracker->PushInstant(
1215       timestamp, signal_deliver_id_, utid, RefType::kRefUtid);
1216 
1217   context_->args_tracker->AddArgsTo(id).AddArg(signal_name_id_,
1218                                                Variadic::Integer(sig.sig()));
1219 }
1220 
ParseLowmemoryKill(int64_t timestamp,ConstBytes blob)1221 void FtraceParser::ParseLowmemoryKill(int64_t timestamp, ConstBytes blob) {
1222   // TODO(hjd): Store the pagecache_size, pagecache_limit and free fields
1223   // in an args table
1224   protos::pbzero::LowmemoryKillFtraceEvent::Decoder lmk(blob.data, blob.size);
1225 
1226   // Store the pid of the event that is lmk-ed.
1227   auto pid = static_cast<uint32_t>(lmk.pid());
1228   auto opt_utid = context_->process_tracker->GetThreadOrNull(pid);
1229 
1230   // Don't add LMK events for threads we've never seen before. This works
1231   // around the case where we get an LMK event after a thread has already been
1232   // killed.
1233   if (!opt_utid)
1234     return;
1235 
1236   InstantId id = context_->event_tracker->PushInstant(
1237       timestamp, lmk_id_, opt_utid.value(), RefType::kRefUtid, true);
1238 
1239   // Store the comm as an arg.
1240   auto comm_id = context_->storage->InternString(
1241       lmk.has_comm() ? lmk.comm() : base::StringView());
1242   context_->args_tracker->AddArgsTo(id).AddArg(comm_name_id_,
1243                                                Variadic::String(comm_id));
1244 }
1245 
ParseOOMScoreAdjUpdate(int64_t timestamp,ConstBytes blob)1246 void FtraceParser::ParseOOMScoreAdjUpdate(int64_t timestamp, ConstBytes blob) {
1247   protos::pbzero::OomScoreAdjUpdateFtraceEvent::Decoder evt(blob.data,
1248                                                             blob.size);
1249   // The int16_t static cast is because older version of the on-device tracer
1250   // had a bug on negative varint encoding (b/120618641).
1251   int16_t oom_adj = static_cast<int16_t>(evt.oom_score_adj());
1252   uint32_t tid = static_cast<uint32_t>(evt.pid());
1253   UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
1254   context_->event_tracker->PushProcessCounterForThread(timestamp, oom_adj,
1255                                                        oom_score_adj_id_, utid);
1256 }
1257 
ParseOOMKill(int64_t timestamp,ConstBytes blob)1258 void FtraceParser::ParseOOMKill(int64_t timestamp, ConstBytes blob) {
1259   protos::pbzero::MarkVictimFtraceEvent::Decoder evt(blob.data, blob.size);
1260   UniqueTid utid = context_->process_tracker->GetOrCreateThread(
1261       static_cast<uint32_t>(evt.pid()));
1262   context_->event_tracker->PushInstant(timestamp, oom_kill_id_, utid,
1263                                        RefType::kRefUtid, true);
1264 }
1265 
ParseMmEventRecord(int64_t timestamp,uint32_t pid,ConstBytes blob)1266 void FtraceParser::ParseMmEventRecord(int64_t timestamp,
1267                                       uint32_t pid,
1268                                       ConstBytes blob) {
1269   protos::pbzero::MmEventRecordFtraceEvent::Decoder evt(blob.data, blob.size);
1270   uint32_t type = evt.type();
1271   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1272 
1273   if (type >= mm_event_counter_names_.size()) {
1274     context_->storage->IncrementStats(stats::mm_unknown_type);
1275     return;
1276   }
1277 
1278   const auto& counter_names = mm_event_counter_names_[type];
1279   context_->event_tracker->PushProcessCounterForThread(
1280       timestamp, evt.count(), counter_names.count, utid);
1281   context_->event_tracker->PushProcessCounterForThread(
1282       timestamp, evt.max_lat(), counter_names.max_lat, utid);
1283   context_->event_tracker->PushProcessCounterForThread(
1284       timestamp, evt.avg_lat(), counter_names.avg_lat, utid);
1285 }
1286 
ParseSysEvent(int64_t timestamp,uint32_t pid,bool is_enter,ConstBytes blob)1287 void FtraceParser::ParseSysEvent(int64_t timestamp,
1288                                  uint32_t pid,
1289                                  bool is_enter,
1290                                  ConstBytes blob) {
1291   protos::pbzero::SysEnterFtraceEvent::Decoder evt(blob.data, blob.size);
1292   uint32_t syscall_num = static_cast<uint32_t>(evt.id());
1293   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1294 
1295   SyscallTracker* syscall_tracker = SyscallTracker::GetOrCreate(context_);
1296   if (is_enter) {
1297     syscall_tracker->Enter(timestamp, utid, syscall_num);
1298   } else {
1299     syscall_tracker->Exit(timestamp, utid, syscall_num);
1300   }
1301 
1302   // We are reusing the same function for sys_enter and sys_exit.
1303   // It is fine as the arguments are the same, but we need to be sure that the
1304   // protobuf field id for both are the same.
1305   static_assert(
1306       static_cast<int>(protos::pbzero::SysEnterFtraceEvent::kIdFieldNumber) ==
1307           static_cast<int>(protos::pbzero::SysExitFtraceEvent::kIdFieldNumber),
1308       "field mismatch");
1309 }
1310 
ParseTaskNewTask(int64_t timestamp,uint32_t source_tid,ConstBytes blob)1311 void FtraceParser::ParseTaskNewTask(int64_t timestamp,
1312                                     uint32_t source_tid,
1313                                     ConstBytes blob) {
1314   protos::pbzero::TaskNewtaskFtraceEvent::Decoder evt(blob.data, blob.size);
1315   uint32_t clone_flags = static_cast<uint32_t>(evt.clone_flags());
1316   uint32_t new_tid = static_cast<uint32_t>(evt.pid());
1317   StringId new_comm = context_->storage->InternString(evt.comm());
1318   auto* proc_tracker = context_->process_tracker.get();
1319 
1320   // task_newtask is raised both in the case of a new process creation (fork()
1321   // family) and thread creation (clone(CLONE_THREAD, ...)).
1322   static const uint32_t kCloneThread = 0x00010000;  // From kernel's sched.h.
1323 
1324   // If the process is a fork, start a new process except if the source tid is
1325   // kthreadd in which case just make it a new thread associated with
1326   // kthreadd.
1327   if ((clone_flags & kCloneThread) == 0 && source_tid != kKthreaddPid) {
1328     // This is a plain-old fork() or equivalent.
1329     proc_tracker->StartNewProcess(timestamp, source_tid, new_tid, new_comm,
1330                                   ThreadNamePriority::kFtrace);
1331     return;
1332   }
1333 
1334   if (source_tid == kKthreaddPid) {
1335     context_->process_tracker->SetProcessMetadata(
1336         kKthreaddPid, base::nullopt, kKthreaddName, base::StringView());
1337   }
1338 
1339   // This is a pthread_create or similar. Bind the two threads together, so
1340   // they get resolved to the same process.
1341   auto source_utid = proc_tracker->GetOrCreateThread(source_tid);
1342   auto new_utid = proc_tracker->StartNewThread(timestamp, new_tid);
1343   proc_tracker->UpdateThreadNameByUtid(new_utid, new_comm,
1344                                        ThreadNamePriority::kFtrace);
1345   proc_tracker->AssociateThreads(source_utid, new_utid);
1346 }
1347 
ParseTaskRename(ConstBytes blob)1348 void FtraceParser::ParseTaskRename(ConstBytes blob) {
1349   protos::pbzero::TaskRenameFtraceEvent::Decoder evt(blob.data, blob.size);
1350   uint32_t tid = static_cast<uint32_t>(evt.pid());
1351   StringId comm = context_->storage->InternString(evt.newcomm());
1352   context_->process_tracker->UpdateThreadNameAndMaybeProcessName(
1353       tid, comm, ThreadNamePriority::kFtrace);
1354 }
1355 
ParseBinderTransaction(int64_t timestamp,uint32_t pid,ConstBytes blob)1356 void FtraceParser::ParseBinderTransaction(int64_t timestamp,
1357                                           uint32_t pid,
1358                                           ConstBytes blob) {
1359   protos::pbzero::BinderTransactionFtraceEvent::Decoder evt(blob.data,
1360                                                             blob.size);
1361   int32_t dest_node = static_cast<int32_t>(evt.target_node());
1362   uint32_t dest_tgid = static_cast<uint32_t>(evt.to_proc());
1363   uint32_t dest_tid = static_cast<uint32_t>(evt.to_thread());
1364   int32_t transaction_id = static_cast<int32_t>(evt.debug_id());
1365   bool is_reply = static_cast<int32_t>(evt.reply()) == 1;
1366   uint32_t flags = static_cast<uint32_t>(evt.flags());
1367   auto code_str = base::IntToHexString(evt.code()) + " Java Layer Dependent";
1368   StringId code = context_->storage->InternString(base::StringView(code_str));
1369   BinderTracker::GetOrCreate(context_)->Transaction(
1370       timestamp, pid, transaction_id, dest_node, dest_tgid, dest_tid, is_reply,
1371       flags, code);
1372 }
1373 
ParseBinderTransactionReceived(int64_t timestamp,uint32_t pid,ConstBytes blob)1374 void FtraceParser::ParseBinderTransactionReceived(int64_t timestamp,
1375                                                   uint32_t pid,
1376                                                   ConstBytes blob) {
1377   protos::pbzero::BinderTransactionReceivedFtraceEvent::Decoder evt(blob.data,
1378                                                                     blob.size);
1379   int32_t transaction_id = static_cast<int32_t>(evt.debug_id());
1380   BinderTracker::GetOrCreate(context_)->TransactionReceived(timestamp, pid,
1381                                                             transaction_id);
1382 }
1383 
ParseBinderTransactionAllocBuf(int64_t timestamp,uint32_t pid,ConstBytes blob)1384 void FtraceParser::ParseBinderTransactionAllocBuf(int64_t timestamp,
1385                                                   uint32_t pid,
1386                                                   ConstBytes blob) {
1387   protos::pbzero::BinderTransactionAllocBufFtraceEvent::Decoder evt(blob.data,
1388                                                                     blob.size);
1389   uint64_t data_size = static_cast<uint64_t>(evt.data_size());
1390   uint64_t offsets_size = static_cast<uint64_t>(evt.offsets_size());
1391 
1392   BinderTracker::GetOrCreate(context_)->TransactionAllocBuf(
1393       timestamp, pid, data_size, offsets_size);
1394 }
1395 
ParseBinderLocked(int64_t timestamp,uint32_t pid,ConstBytes blob)1396 void FtraceParser::ParseBinderLocked(int64_t timestamp,
1397                                      uint32_t pid,
1398                                      ConstBytes blob) {
1399   protos::pbzero::BinderLockedFtraceEvent::Decoder evt(blob.data, blob.size);
1400   BinderTracker::GetOrCreate(context_)->Locked(timestamp, pid);
1401 }
1402 
ParseBinderLock(int64_t timestamp,uint32_t pid,ConstBytes blob)1403 void FtraceParser::ParseBinderLock(int64_t timestamp,
1404                                    uint32_t pid,
1405                                    ConstBytes blob) {
1406   protos::pbzero::BinderLockFtraceEvent::Decoder evt(blob.data, blob.size);
1407   BinderTracker::GetOrCreate(context_)->Lock(timestamp, pid);
1408 }
1409 
ParseBinderUnlock(int64_t timestamp,uint32_t pid,ConstBytes blob)1410 void FtraceParser::ParseBinderUnlock(int64_t timestamp,
1411                                      uint32_t pid,
1412                                      ConstBytes blob) {
1413   protos::pbzero::BinderUnlockFtraceEvent::Decoder evt(blob.data, blob.size);
1414   BinderTracker::GetOrCreate(context_)->Unlock(timestamp, pid);
1415 }
1416 
ParseClockSetRate(int64_t timestamp,ConstBytes blob)1417 void FtraceParser::ParseClockSetRate(int64_t timestamp, ConstBytes blob) {
1418   protos::pbzero::ClockSetRateFtraceEvent::Decoder evt(blob.data, blob.size);
1419   static const char kSubtitle[] = "Frequency";
1420   ClockRate(timestamp, evt.name(), kSubtitle, evt.state());
1421 }
1422 
ParseClockEnable(int64_t timestamp,ConstBytes blob)1423 void FtraceParser::ParseClockEnable(int64_t timestamp, ConstBytes blob) {
1424   protos::pbzero::ClockEnableFtraceEvent::Decoder evt(blob.data, blob.size);
1425   static const char kSubtitle[] = "State";
1426   ClockRate(timestamp, evt.name(), kSubtitle, evt.state());
1427 }
1428 
ParseClockDisable(int64_t timestamp,ConstBytes blob)1429 void FtraceParser::ParseClockDisable(int64_t timestamp, ConstBytes blob) {
1430   protos::pbzero::ClockDisableFtraceEvent::Decoder evt(blob.data, blob.size);
1431   static const char kSubtitle[] = "State";
1432   ClockRate(timestamp, evt.name(), kSubtitle, evt.state());
1433 }
1434 
ClockRate(int64_t timestamp,base::StringView clock_name,base::StringView subtitle,uint64_t rate)1435 void FtraceParser::ClockRate(int64_t timestamp,
1436                              base::StringView clock_name,
1437                              base::StringView subtitle,
1438                              uint64_t rate) {
1439   base::StackString<255> counter_name("%.*s %.*s", int(clock_name.size()),
1440                                       clock_name.data(), int(subtitle.size()),
1441                                       subtitle.data());
1442   StringId name = context_->storage->InternString(counter_name.c_str());
1443   TrackId track = context_->track_tracker->InternGlobalCounterTrack(name);
1444   context_->event_tracker->PushCounter(timestamp, static_cast<double>(rate),
1445                                        track);
1446 }
1447 
ParseScmCallStart(int64_t timestamp,uint32_t pid,ConstBytes blob)1448 void FtraceParser::ParseScmCallStart(int64_t timestamp,
1449                                      uint32_t pid,
1450                                      ConstBytes blob) {
1451   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1452   TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
1453   protos::pbzero::ScmCallStartFtraceEvent::Decoder evt(blob.data, blob.size);
1454 
1455   char str[64];
1456   sprintf(str, "scm id=%#" PRIx64, evt.x0());
1457   StringId name_id = context_->storage->InternString(str);
1458   context_->slice_tracker->Begin(timestamp, track_id, kNullStringId, name_id);
1459 }
1460 
ParseScmCallEnd(int64_t timestamp,uint32_t pid,ConstBytes blob)1461 void FtraceParser::ParseScmCallEnd(int64_t timestamp,
1462                                    uint32_t pid,
1463                                    ConstBytes blob) {
1464   protos::pbzero::ScmCallEndFtraceEvent::Decoder evt(blob.data, blob.size);
1465   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1466   TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
1467   context_->slice_tracker->End(timestamp, track_id);
1468 }
1469 
ParseDirectReclaimBegin(int64_t timestamp,uint32_t pid,ConstBytes blob)1470 void FtraceParser::ParseDirectReclaimBegin(int64_t timestamp,
1471                                            uint32_t pid,
1472                                            ConstBytes blob) {
1473   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1474   TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
1475   protos::pbzero::MmVmscanDirectReclaimBeginFtraceEvent::Decoder
1476       direct_reclaim_begin(blob.data, blob.size);
1477 
1478   StringId name_id =
1479       context_->storage->InternString("mm_vmscan_direct_reclaim");
1480 
1481   auto args_inserter = [this, &direct_reclaim_begin](
1482                            ArgsTracker::BoundInserter* inserter) {
1483     inserter->AddArg(direct_reclaim_order_id_,
1484                      Variadic::Integer(direct_reclaim_begin.order()));
1485     inserter->AddArg(direct_reclaim_may_writepage_id_,
1486                      Variadic::Integer(direct_reclaim_begin.may_writepage()));
1487     inserter->AddArg(
1488         direct_reclaim_gfp_flags_id_,
1489         Variadic::UnsignedInteger(direct_reclaim_begin.gfp_flags()));
1490   };
1491   context_->slice_tracker->Begin(timestamp, track_id, kNullStringId, name_id,
1492                                  args_inserter);
1493 }
1494 
ParseDirectReclaimEnd(int64_t timestamp,uint32_t pid,ConstBytes blob)1495 void FtraceParser::ParseDirectReclaimEnd(int64_t timestamp,
1496                                          uint32_t pid,
1497                                          ConstBytes blob) {
1498   protos::pbzero::ScmCallEndFtraceEvent::Decoder evt(blob.data, blob.size);
1499   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1500   TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
1501   protos::pbzero::MmVmscanDirectReclaimEndFtraceEvent::Decoder
1502       direct_reclaim_end(blob.data, blob.size);
1503 
1504   auto args_inserter =
1505       [this, &direct_reclaim_end](ArgsTracker::BoundInserter* inserter) {
1506         inserter->AddArg(
1507             direct_reclaim_nr_reclaimed_id_,
1508             Variadic::UnsignedInteger(direct_reclaim_end.nr_reclaimed()));
1509       };
1510   context_->slice_tracker->End(timestamp, track_id, kNullStringId,
1511                                kNullStringId, args_inserter);
1512 }
1513 
ParseWorkqueueExecuteStart(uint32_t cpu,int64_t timestamp,uint32_t pid,ConstBytes blob,PacketSequenceStateGeneration * seq_state)1514 void FtraceParser::ParseWorkqueueExecuteStart(
1515     uint32_t cpu,
1516     int64_t timestamp,
1517     uint32_t pid,
1518     ConstBytes blob,
1519     PacketSequenceStateGeneration* seq_state) {
1520   protos::pbzero::WorkqueueExecuteStartFtraceEvent::Decoder evt(blob.data,
1521                                                                 blob.size);
1522 
1523   auto* interned_string = seq_state->LookupInternedMessage<
1524       protos::pbzero::InternedData::kKernelSymbolsFieldNumber,
1525       protos::pbzero::InternedString>(static_cast<uint32_t>(evt.function()));
1526   StringId name_id;
1527   if (interned_string) {
1528     protozero::ConstBytes str = interned_string->str();
1529     name_id = context_->storage->InternString(
1530         base::StringView(reinterpret_cast<const char*>(str.data), str.size));
1531   } else {
1532     base::StackString<255> slice_name("%#" PRIx64, evt.function());
1533     name_id = context_->storage->InternString(slice_name.string_view());
1534   }
1535 
1536   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1537   TrackId track = context_->track_tracker->InternThreadTrack(utid);
1538 
1539   auto args_inserter = [this, cpu](ArgsTracker::BoundInserter* inserter) {
1540     inserter->AddArg(cpu_id_, Variadic::Integer(cpu));
1541   };
1542   context_->slice_tracker->Begin(timestamp, track, workqueue_id_, name_id,
1543                                  args_inserter);
1544 }
1545 
ParseWorkqueueExecuteEnd(int64_t timestamp,uint32_t pid,ConstBytes blob)1546 void FtraceParser::ParseWorkqueueExecuteEnd(int64_t timestamp,
1547                                             uint32_t pid,
1548                                             ConstBytes blob) {
1549   protos::pbzero::WorkqueueExecuteEndFtraceEvent::Decoder evt(blob.data,
1550                                                               blob.size);
1551   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1552   TrackId track = context_->track_tracker->InternThreadTrack(utid);
1553   context_->slice_tracker->End(timestamp, track, workqueue_id_);
1554 }
1555 
ParseIrqHandlerEntry(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)1556 void FtraceParser::ParseIrqHandlerEntry(uint32_t cpu,
1557                                         int64_t timestamp,
1558                                         protozero::ConstBytes blob) {
1559   protos::pbzero::IrqHandlerEntryFtraceEvent::Decoder evt(blob.data, blob.size);
1560   base::StackString<255> track_name("Irq Cpu %d", cpu);
1561   StringId track_name_id =
1562       context_->storage->InternString(track_name.string_view());
1563 
1564   base::StringView irq_name = evt.name();
1565   base::StackString<255> slice_name("IRQ (%.*s)", int(irq_name.size()),
1566                                     irq_name.data());
1567   StringId slice_name_id =
1568       context_->storage->InternString(slice_name.string_view());
1569   TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
1570   context_->slice_tracker->Begin(timestamp, track, irq_id_, slice_name_id);
1571 }
1572 
ParseIrqHandlerExit(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)1573 void FtraceParser::ParseIrqHandlerExit(uint32_t cpu,
1574                                        int64_t timestamp,
1575                                        protozero::ConstBytes blob) {
1576   protos::pbzero::IrqHandlerExitFtraceEvent::Decoder evt(blob.data, blob.size);
1577   base::StackString<255> track_name("Irq Cpu %d", cpu);
1578   StringId track_name_id =
1579       context_->storage->InternString(track_name.string_view());
1580   TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
1581 
1582   base::StackString<255> status("%s", evt.ret() == 1 ? "handled" : "unhandled");
1583   StringId status_id = context_->storage->InternString(status.string_view());
1584   auto args_inserter = [this,
1585                         &status_id](ArgsTracker::BoundInserter* inserter) {
1586     inserter->AddArg(ret_arg_id_, Variadic::String(status_id));
1587   };
1588   context_->slice_tracker->End(timestamp, track, irq_id_, {}, args_inserter);
1589 }
1590 
ParseSoftIrqEntry(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)1591 void FtraceParser::ParseSoftIrqEntry(uint32_t cpu,
1592                                      int64_t timestamp,
1593                                      protozero::ConstBytes blob) {
1594   protos::pbzero::SoftirqEntryFtraceEvent::Decoder evt(blob.data, blob.size);
1595   base::StackString<255> track_name("SoftIrq Cpu %d", cpu);
1596   StringId track_name_id =
1597       context_->storage->InternString(track_name.string_view());
1598   auto num_actions = sizeof(kActionNames) / sizeof(*kActionNames);
1599   if (evt.vec() >= num_actions) {
1600     PERFETTO_DFATAL("No action name at index %d for softirq event.", evt.vec());
1601     return;
1602   }
1603   base::StringView slice_name = kActionNames[evt.vec()];
1604   StringId slice_name_id = context_->storage->InternString(slice_name);
1605   TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
1606   context_->slice_tracker->Begin(timestamp, track, irq_id_, slice_name_id);
1607 }
1608 
ParseSoftIrqExit(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)1609 void FtraceParser::ParseSoftIrqExit(uint32_t cpu,
1610                                     int64_t timestamp,
1611                                     protozero::ConstBytes blob) {
1612   protos::pbzero::SoftirqExitFtraceEvent::Decoder evt(blob.data, blob.size);
1613   base::StackString<255> track_name("SoftIrq Cpu %d", cpu);
1614   StringId track_name_id =
1615       context_->storage->InternString(track_name.string_view());
1616   TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
1617   auto vec = evt.vec();
1618   auto args_inserter = [this, vec](ArgsTracker::BoundInserter* inserter) {
1619     inserter->AddArg(vec_arg_id_, Variadic::Integer(vec));
1620   };
1621   context_->slice_tracker->End(timestamp, track, irq_id_, {}, args_inserter);
1622 }
1623 
ParseGpuMemTotal(int64_t timestamp,protozero::ConstBytes data)1624 void FtraceParser::ParseGpuMemTotal(int64_t timestamp,
1625                                     protozero::ConstBytes data) {
1626   protos::pbzero::GpuMemTotalFtraceEvent::Decoder gpu_mem_total(data.data,
1627                                                                 data.size);
1628 
1629   TrackId track = kInvalidTrackId;
1630   const uint32_t pid = gpu_mem_total.pid();
1631   if (pid == 0) {
1632     // Pid 0 is used to indicate the global total
1633     track = context_->track_tracker->InternGlobalCounterTrack(
1634         gpu_mem_total_name_id_, gpu_mem_total_unit_id_,
1635         gpu_mem_total_global_desc_id_);
1636   } else {
1637     // It's possible for GpuMemTotal ftrace events to be emitted by kworker
1638     // threads *after* process death. In this case, we simply want to discard
1639     // the event as otherwise we would create fake processes which we
1640     // definitely want to avoid.
1641     // See b/192274404 for more info.
1642     base::Optional<UniqueTid> opt_utid =
1643         context_->process_tracker->GetThreadOrNull(pid);
1644     if (!opt_utid)
1645       return;
1646 
1647     // If the thread does exist, the |pid| in gpu_mem_total events is always a
1648     // true process id (and not a thread id) so ensure there is an association
1649     // between the tid and pid.
1650     UniqueTid updated_utid = context_->process_tracker->UpdateThread(pid, pid);
1651     PERFETTO_DCHECK(updated_utid == *opt_utid);
1652 
1653     // UpdateThread above should ensure this is always set.
1654     UniquePid upid = *context_->storage->thread_table().upid()[*opt_utid];
1655     PERFETTO_DCHECK(context_->storage->process_table().pid()[upid] == pid);
1656 
1657     track = context_->track_tracker->InternProcessCounterTrack(
1658         gpu_mem_total_name_id_, upid, gpu_mem_total_unit_id_,
1659         gpu_mem_total_proc_desc_id_);
1660   }
1661   context_->event_tracker->PushCounter(
1662       timestamp, static_cast<double>(gpu_mem_total.size()), track);
1663 }
1664 
ParseThermalTemperature(int64_t timestamp,protozero::ConstBytes blob)1665 void FtraceParser::ParseThermalTemperature(int64_t timestamp,
1666                                            protozero::ConstBytes blob) {
1667   protos::pbzero::ThermalTemperatureFtraceEvent::Decoder evt(blob.data,
1668                                                              blob.size);
1669   base::StringView thermal_zone = evt.thermal_zone();
1670   base::StackString<255> counter_name(
1671       "%.*s Temperature", int(thermal_zone.size()), thermal_zone.data());
1672   StringId name = context_->storage->InternString(counter_name.string_view());
1673   TrackId track = context_->track_tracker->InternGlobalCounterTrack(name);
1674   context_->event_tracker->PushCounter(timestamp, evt.temp(), track);
1675 }
1676 
ParseCdevUpdate(int64_t timestamp,protozero::ConstBytes blob)1677 void FtraceParser::ParseCdevUpdate(int64_t timestamp,
1678                                    protozero::ConstBytes blob) {
1679   protos::pbzero::CdevUpdateFtraceEvent::Decoder evt(blob.data, blob.size);
1680   base::StringView type = evt.type();
1681   base::StackString<255> counter_name("%.*s Cooling Device", int(type.size()),
1682                                       type.data());
1683   StringId name = context_->storage->InternString(counter_name.string_view());
1684   TrackId track = context_->track_tracker->InternGlobalCounterTrack(name);
1685   context_->event_tracker->PushCounter(
1686       timestamp, static_cast<double>(evt.target()), track);
1687 }
1688 
ParseSchedBlockedReason(int64_t timestamp,protozero::ConstBytes blob,PacketSequenceStateGeneration * seq_state)1689 void FtraceParser::ParseSchedBlockedReason(
1690     int64_t timestamp,
1691     protozero::ConstBytes blob,
1692     PacketSequenceStateGeneration* seq_state) {
1693   protos::pbzero::SchedBlockedReasonFtraceEvent::Decoder evt(blob);
1694   uint32_t pid = static_cast<uint32_t>(evt.pid());
1695   auto utid = context_->process_tracker->GetOrCreateThread(pid);
1696   InstantId id = context_->event_tracker->PushInstant(
1697       timestamp, sched_blocked_reason_id_, utid, RefType::kRefUtid, false);
1698 
1699   auto inserter = context_->args_tracker->AddArgsTo(id);
1700   inserter.AddArg(io_wait_id_, Variadic::Boolean(evt.io_wait()));
1701 
1702   uint32_t caller_iid = static_cast<uint32_t>(evt.caller());
1703   auto* interned_string = seq_state->LookupInternedMessage<
1704       protos::pbzero::InternedData::kKernelSymbolsFieldNumber,
1705       protos::pbzero::InternedString>(caller_iid);
1706 
1707   if (interned_string) {
1708     protozero::ConstBytes str = interned_string->str();
1709     StringId str_id = context_->storage->InternString(
1710         base::StringView(reinterpret_cast<const char*>(str.data), str.size));
1711     inserter.AddArg(function_id_, Variadic::String(str_id));
1712   }
1713 }
1714 
ParseFastRpcDmaStat(int64_t timestamp,uint32_t pid,protozero::ConstBytes blob)1715 void FtraceParser::ParseFastRpcDmaStat(int64_t timestamp,
1716                                        uint32_t pid,
1717                                        protozero::ConstBytes blob) {
1718   protos::pbzero::FastrpcDmaStatFtraceEvent::Decoder evt(blob.data, blob.size);
1719 
1720   StringId name;
1721   if (0 <= evt.cid() && evt.cid() < static_cast<int32_t>(kFastRpcCounterSize)) {
1722     name = fast_rpc_delta_names_[static_cast<size_t>(evt.cid())];
1723   } else {
1724     base::StackString<64> str("mem.fastrpc[%" PRId32 "]", evt.cid());
1725     name = context_->storage->InternString(str.string_view());
1726   }
1727 
1728   StringId total_name;
1729   if (0 <= evt.cid() && evt.cid() < static_cast<int32_t>(kFastRpcCounterSize)) {
1730     total_name = fast_rpc_total_names_[static_cast<size_t>(evt.cid())];
1731   } else {
1732     base::StackString<64> str("mem.fastrpc[%" PRId32 "]", evt.cid());
1733     total_name = context_->storage->InternString(str.string_view());
1734   }
1735 
1736   // Push the global counter.
1737   TrackId track = context_->track_tracker->InternGlobalCounterTrack(total_name);
1738   context_->event_tracker->PushCounter(
1739       timestamp, static_cast<double>(evt.total_allocated()), track);
1740 
1741   // Push the change counter.
1742   // TODO(b/121331269): these should really be instant events.
1743   UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1744   TrackId delta_track =
1745       context_->track_tracker->InternThreadCounterTrack(name, utid);
1746   context_->event_tracker->PushCounter(
1747       timestamp, static_cast<double>(evt.len()), delta_track);
1748 }
1749 
ParseCpuhpPause(int64_t,uint32_t,protozero::ConstBytes blob)1750 void FtraceParser::ParseCpuhpPause(int64_t,
1751                                    uint32_t,
1752                                    protozero::ConstBytes blob) {
1753   protos::pbzero::CpuhpPauseFtraceEvent::Decoder evt(blob.data, blob.size);
1754   // TODO(b/183110813): Parse and visualize this event.
1755 }
1756 
ParseNetifReceiveSkb(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)1757 void FtraceParser::ParseNetifReceiveSkb(uint32_t cpu,
1758                                         int64_t timestamp,
1759                                         protozero::ConstBytes blob) {
1760   protos::pbzero::NetifReceiveSkbFtraceEvent::Decoder evt(blob.data, blob.size);
1761   base::StringView net_device = evt.name();
1762   base::StackString<255> counter_name("%.*s Received KB",
1763                                       static_cast<int>(net_device.size()),
1764                                       net_device.data());
1765   StringId name = context_->storage->InternString(counter_name.string_view());
1766 
1767   nic_received_bytes_[name] += evt.len();
1768 
1769   uint64_t nic_received_kilobytes = nic_received_bytes_[name] / 1024;
1770   TrackId track = context_->track_tracker->InternGlobalCounterTrack(name);
1771   base::Optional<CounterId> id = context_->event_tracker->PushCounter(
1772       timestamp, static_cast<double>(nic_received_kilobytes), track);
1773   if (!id) {
1774     return;
1775   }
1776   // Store cpu & len as args for metrics computation
1777   StringId cpu_key = context_->storage->InternString("cpu");
1778   StringId len_key = context_->storage->InternString("len");
1779   context_->args_tracker->AddArgsTo(*id)
1780       .AddArg(cpu_key, Variadic::UnsignedInteger(cpu))
1781       .AddArg(len_key, Variadic::UnsignedInteger(evt.len()));
1782 }
1783 
ParseNetDevXmit(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)1784 void FtraceParser::ParseNetDevXmit(uint32_t cpu,
1785                                    int64_t timestamp,
1786                                    protozero::ConstBytes blob) {
1787   protos::pbzero::NetDevXmitFtraceEvent::Decoder evt(blob.data, blob.size);
1788   base::StringView net_device = evt.name();
1789   base::StackString<255> counter_name("%.*s Transmitted KB",
1790                                       static_cast<int>(net_device.size()),
1791                                       net_device.data());
1792   StringId name = context_->storage->InternString(counter_name.string_view());
1793 
1794   // Make sure driver took care of packet.
1795   if (evt.rc() != 0) {
1796     return;
1797   }
1798   nic_transmitted_bytes_[name] += evt.len();
1799 
1800   uint64_t nic_transmitted_kilobytes = nic_transmitted_bytes_[name] / 1024;
1801   TrackId track = context_->track_tracker->InternGlobalCounterTrack(name);
1802   base::Optional<CounterId> id = context_->event_tracker->PushCounter(
1803       timestamp, static_cast<double>(nic_transmitted_kilobytes), track);
1804   if (!id) {
1805     return;
1806   }
1807   // Store cpu & len as args for metrics computation.
1808   context_->args_tracker->AddArgsTo(*id)
1809       .AddArg(cpu_id_, Variadic::UnsignedInteger(cpu))
1810       .AddArg(len_arg_id_, Variadic::UnsignedInteger(evt.len()));
1811 }
1812 
ParseInetSockSetState(int64_t timestamp,uint32_t pid,protozero::ConstBytes blob)1813 void FtraceParser::ParseInetSockSetState(int64_t timestamp,
1814                                          uint32_t pid,
1815                                          protozero::ConstBytes blob) {
1816   protos::pbzero::InetSockSetStateFtraceEvent::Decoder evt(blob.data,
1817                                                            blob.size);
1818 
1819   // Skip non TCP protocol.
1820   if (evt.protocol() != kIpprotoTcp) {
1821     PERFETTO_ELOG("skip non tcp protocol");
1822     return;
1823   }
1824 
1825   // Skip non IP protocol.
1826   if (evt.family() != kAfNet && evt.family() != kAfNet6) {
1827     PERFETTO_ELOG("skip non IP protocol");
1828     return;
1829   }
1830 
1831   // Skip invalid TCP state.
1832   if (evt.newstate() >= TCP_MAX_STATES || evt.oldstate() >= TCP_MAX_STATES) {
1833     PERFETTO_ELOG("skip invalid tcp state");
1834     return;
1835   }
1836 
1837   auto got = skaddr_to_stream_.find(evt.skaddr());
1838   if (got == skaddr_to_stream_.end()) {
1839     skaddr_to_stream_[evt.skaddr()] = ++num_of_tcp_stream_;
1840   }
1841   uint32_t stream = skaddr_to_stream_[evt.skaddr()];
1842   char stream_str[64];
1843   sprintf(stream_str, "TCP stream#%" PRIu32 "", stream);
1844   StringId stream_id = context_->storage->InternString(stream_str);
1845 
1846   StringId slice_name_id;
1847   if (evt.newstate() == TCP_SYN_SENT) {
1848     base::StackString<32> str("%s(pid=%" PRIu32 ")",
1849                               kTcpStateNames[evt.newstate()], pid);
1850     slice_name_id = context_->storage->InternString(str.string_view());
1851   } else if (evt.newstate() == TCP_ESTABLISHED) {
1852     base::StackString<64> str("%s(sport=%" PRIu32 ",dport=%" PRIu32 ")",
1853                               kTcpStateNames[evt.newstate()], evt.sport(),
1854                               evt.dport());
1855     slice_name_id = context_->storage->InternString(str.string_view());
1856   } else {
1857     base::StringView slice_name = kTcpStateNames[evt.newstate()];
1858     slice_name_id = context_->storage->InternString(slice_name);
1859   }
1860 
1861   // Push to async task set tracker.
1862   auto async_track =
1863       context_->async_track_set_tracker->InternGlobalTrackSet(stream_id);
1864   TrackId end_id = context_->async_track_set_tracker->End(
1865       async_track, static_cast<int64_t>(evt.skaddr()));
1866   context_->slice_tracker->End(timestamp, end_id);
1867   TrackId start_id = context_->async_track_set_tracker->Begin(
1868       async_track, static_cast<int64_t>(evt.skaddr()));
1869   context_->slice_tracker->Begin(timestamp, start_id, tcp_state_id_,
1870                                  slice_name_id);
1871 }
1872 
ParseTcpRetransmitSkb(int64_t timestamp,protozero::ConstBytes blob)1873 void FtraceParser::ParseTcpRetransmitSkb(int64_t timestamp,
1874                                          protozero::ConstBytes blob) {
1875   protos::pbzero::TcpRetransmitSkbFtraceEvent::Decoder evt(blob.data,
1876                                                            blob.size);
1877 
1878   // Push event as instant to async task set tracker.
1879   auto async_track = context_->async_track_set_tracker->InternGlobalTrackSet(
1880       tcp_retransmited_name_id_);
1881   base::StackString<64> str("sport=%" PRIu32 ",dport=%" PRIu32 "", evt.sport(),
1882                             evt.dport());
1883   StringId slice_name_id = context_->storage->InternString(str.string_view());
1884   TrackId track_id =
1885       context_->async_track_set_tracker->Scoped(async_track, timestamp, 0);
1886   context_->slice_tracker->Scoped(timestamp, track_id, tcp_event_id_,
1887                                   slice_name_id, 0);
1888 }
1889 
ParseNapiGroReceiveEntry(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)1890 void FtraceParser::ParseNapiGroReceiveEntry(uint32_t cpu,
1891                                             int64_t timestamp,
1892                                             protozero::ConstBytes blob) {
1893   protos::pbzero::NapiGroReceiveEntryFtraceEvent::Decoder evt(blob.data,
1894                                                               blob.size);
1895   base::StackString<255> track_name("Napi Gro Cpu %d", cpu);
1896   StringId track_name_id =
1897       context_->storage->InternString(track_name.string_view());
1898   base::StringView net_device = evt.name();
1899   StringId slice_name_id = context_->storage->InternString(net_device);
1900   TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
1901   auto len = evt.len();
1902   auto args_inserter = [this, len](ArgsTracker::BoundInserter* inserter) {
1903     inserter->AddArg(len_arg_id_, Variadic::Integer(len));
1904   };
1905   context_->slice_tracker->Begin(timestamp, track, napi_gro_id_, slice_name_id,
1906                                  args_inserter);
1907 }
1908 
ParseNapiGroReceiveExit(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)1909 void FtraceParser::ParseNapiGroReceiveExit(uint32_t cpu,
1910                                            int64_t timestamp,
1911                                            protozero::ConstBytes blob) {
1912   protos::pbzero::NapiGroReceiveExitFtraceEvent::Decoder evt(blob.data,
1913                                                              blob.size);
1914   base::StackString<255> track_name("Napi Gro Cpu %d", cpu);
1915   StringId track_name_id =
1916       context_->storage->InternString(track_name.string_view());
1917   TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
1918   auto ret = evt.ret();
1919   auto args_inserter = [this, ret](ArgsTracker::BoundInserter* inserter) {
1920     inserter->AddArg(ret_arg_id_, Variadic::Integer(ret));
1921   };
1922   context_->slice_tracker->End(timestamp, track, napi_gro_id_, {},
1923                                args_inserter);
1924 }
1925 
ParseCpuFrequencyLimits(int64_t timestamp,protozero::ConstBytes blob)1926 void FtraceParser::ParseCpuFrequencyLimits(int64_t timestamp,
1927                                            protozero::ConstBytes blob) {
1928   protos::pbzero::CpuFrequencyLimitsFtraceEvent::Decoder evt(blob.data,
1929                                                              blob.size);
1930   base::StackString<255> max_counter_name("Cpu %" PRIu32 " Max Freq Limit",
1931                                           evt.cpu_id());
1932   base::StackString<255> min_counter_name("Cpu %" PRIu32 " Min Freq Limit",
1933                                           evt.cpu_id());
1934   // Push max freq to global counter.
1935   StringId max_name = context_->storage->InternString(max_counter_name.c_str());
1936   TrackId max_track =
1937       context_->track_tracker->InternGlobalCounterTrack(max_name);
1938   context_->event_tracker->PushCounter(
1939       timestamp, static_cast<double>(evt.max_freq()), max_track);
1940 
1941   // Push min freq to global counter.
1942   StringId min_name = context_->storage->InternString(min_counter_name.c_str());
1943   TrackId min_track =
1944       context_->track_tracker->InternGlobalCounterTrack(min_name);
1945   context_->event_tracker->PushCounter(
1946       timestamp, static_cast<double>(evt.min_freq()), min_track);
1947 }
1948 
ParseKfreeSkb(int64_t timestamp,protozero::ConstBytes blob)1949 void FtraceParser::ParseKfreeSkb(int64_t timestamp,
1950                                  protozero::ConstBytes blob) {
1951   protos::pbzero::KfreeSkbFtraceEvent::Decoder evt(blob.data, blob.size);
1952 
1953   // Skip non IP & IPV6 protocol.
1954   if (evt.protocol() != kEthPIp && evt.protocol() != kEthPIp6) {
1955     return;
1956   }
1957   num_of_kfree_skb_ip_prot += 1;
1958 
1959   TrackId track =
1960       context_->track_tracker->InternGlobalCounterTrack(kfree_skb_name_id_);
1961   base::Optional<CounterId> id = context_->event_tracker->PushCounter(
1962       timestamp, static_cast<double>(num_of_kfree_skb_ip_prot), track);
1963   if (!id) {
1964     return;
1965   }
1966   base::StackString<255> prot("%s", evt.protocol() == kEthPIp ? "IP" : "IPV6");
1967   StringId prot_id = context_->storage->InternString(prot.string_view());
1968   // Store protocol as args for metrics computation.
1969   context_->args_tracker->AddArgsTo(*id).AddArg(
1970       protocol_arg_id_, Variadic::String(prot_id));
1971 }
1972 
ParseCrosEcSensorhubData(int64_t timestamp,protozero::ConstBytes blob)1973 void FtraceParser::ParseCrosEcSensorhubData(int64_t timestamp,
1974                                             protozero::ConstBytes blob) {
1975   protos::pbzero::CrosEcSensorhubDataFtraceEvent::Decoder evt(blob.data,
1976                                                               blob.size);
1977 
1978   // Push the global counter.
1979   TrackId track = context_->track_tracker->InternGlobalCounterTrack(
1980       context_->storage->InternString(
1981           base::StringView("cros_ec.cros_ec_sensorhub_data." +
1982                            std::to_string(evt.ec_sensor_num()))));
1983 
1984   auto args_inserter = [this, &evt](ArgsTracker::BoundInserter* inserter) {
1985     inserter->AddArg(cros_ec_arg_num_id_,
1986                      Variadic::Integer(evt.ec_sensor_num()));
1987     inserter->AddArg(
1988         cros_ec_arg_ec_id_,
1989         Variadic::Integer(evt.fifo_timestamp() - evt.current_timestamp()));
1990     inserter->AddArg(cros_ec_arg_sample_ts_id_,
1991                      Variadic::Integer(evt.current_timestamp()));
1992   };
1993 
1994   context_->event_tracker->PushCounter(
1995       timestamp,
1996       static_cast<double>(evt.current_time() - evt.current_timestamp()), track,
1997       args_inserter);
1998 }
1999 
ParseUfshcdClkGating(int64_t timestamp,protozero::ConstBytes blob)2000 void FtraceParser::ParseUfshcdClkGating(int64_t timestamp,
2001                                       protozero::ConstBytes blob) {
2002   protos::pbzero::UfshcdClkGatingFtraceEvent::Decoder evt(blob.data, blob.size);
2003   int32_t clk_state = 0;
2004 
2005   switch (evt.state()) {
2006       case 1:
2007           // Change ON state to 3
2008           clk_state = 3;
2009           break;
2010       case 2:
2011           // Change REQ_OFF state to 1
2012           clk_state = 1;
2013           break;
2014       case 3:
2015           // Change REQ_ON state to 2
2016           clk_state = 2;
2017           break;
2018   }
2019   TrackId track = context_->track_tracker->InternGlobalCounterTrack(
2020       ufs_clkgating_id_);
2021   context_->event_tracker->PushCounter(timestamp, static_cast<double>(clk_state),
2022                                        track);
2023 }
2024 
ParseUfshcdCommand(int64_t timestamp,protozero::ConstBytes blob)2025 void FtraceParser::ParseUfshcdCommand(int64_t timestamp,
2026                                       protozero::ConstBytes blob) {
2027   protos::pbzero::UfshcdCommandFtraceEvent::Decoder evt(blob.data, blob.size);
2028   uint32_t num = evt.doorbell() > 0 ?
2029       static_cast<uint32_t>(PERFETTO_POPCOUNT(evt.doorbell())) :
2030       (evt.str_t() == 1 ? 0 : 1);
2031 
2032   TrackId track = context_->track_tracker->InternGlobalCounterTrack(
2033       ufs_command_count_id_);
2034   context_->event_tracker->PushCounter(timestamp, static_cast<double>(num),
2035                                        track);
2036 }
2037 
ParseWakeSourceActivate(int64_t timestamp,protozero::ConstBytes blob)2038 void FtraceParser::ParseWakeSourceActivate(int64_t timestamp,
2039                                            protozero::ConstBytes blob) {
2040   protos::pbzero::WakeupSourceActivateFtraceEvent::Decoder evt(blob.data,
2041                                                                blob.size);
2042   std::string event_name = evt.name().ToStdString();
2043 
2044   uint32_t count = active_wakelock_to_count_[event_name];
2045 
2046   active_wakelock_to_count_[event_name] += 1;
2047 
2048   // There is already an active track with this name, don't create another.
2049   if (count > 0) {
2050     return;
2051   }
2052 
2053   base::StackString<32> str("Wakelock(%s)", event_name.c_str());
2054   StringId stream_id = context_->storage->InternString(str.string_view());
2055 
2056   auto async_track =
2057       context_->async_track_set_tracker->InternGlobalTrackSet(stream_id);
2058 
2059   TrackId start_id = context_->async_track_set_tracker->Begin(async_track, 0);
2060 
2061   context_->slice_tracker->Begin(timestamp, start_id, kNullStringId, stream_id);
2062 }
2063 
ParseWakeSourceDeactivate(int64_t timestamp,protozero::ConstBytes blob)2064 void FtraceParser::ParseWakeSourceDeactivate(int64_t timestamp,
2065                                              protozero::ConstBytes blob) {
2066   protos::pbzero::WakeupSourceDeactivateFtraceEvent::Decoder evt(blob.data,
2067                                                                  blob.size);
2068 
2069   std::string event_name = evt.name().ToStdString();
2070   uint32_t count = active_wakelock_to_count_[event_name];
2071   active_wakelock_to_count_[event_name] = count > 0 ? count - 1 : 0;
2072   if (count != 1) {
2073     return;
2074   }
2075 
2076   base::StackString<32> str("Wakelock(%s)", event_name.c_str());
2077   StringId stream_id = context_->storage->InternString(str.string_view());
2078   auto async_track =
2079       context_->async_track_set_tracker->InternGlobalTrackSet(stream_id);
2080 
2081   TrackId end_id = context_->async_track_set_tracker->End(async_track, 0);
2082   context_->slice_tracker->End(timestamp, end_id);
2083 }
2084 
ParseSuspendResume(int64_t timestamp,protozero::ConstBytes blob)2085 void FtraceParser::ParseSuspendResume(int64_t timestamp,
2086                                       protozero::ConstBytes blob) {
2087   protos::pbzero::SuspendResumeFtraceEvent::Decoder evt(blob.data, blob.size);
2088 
2089   auto async_track = context_->async_track_set_tracker->InternGlobalTrackSet(
2090       suspend_resume_name_id_);
2091 
2092   base::StackString<64> str("%s(%" PRIu32 ")",
2093                             evt.action().ToStdString().c_str(), evt.val());
2094   StringId slice_name_id = context_->storage->InternString(str.string_view());
2095 
2096   if (evt.start()) {
2097     TrackId start_id = context_->async_track_set_tracker->Begin(
2098         async_track, static_cast<int64_t>(evt.val()));
2099     context_->slice_tracker->Begin(timestamp, start_id, suspend_resume_name_id_,
2100                                    slice_name_id);
2101   } else {
2102     TrackId end_id = context_->async_track_set_tracker->End(
2103         async_track, static_cast<int64_t>(evt.val()));
2104     context_->slice_tracker->End(timestamp, end_id);
2105   }
2106 }
2107 
2108 }  // namespace trace_processor
2109 }  // namespace perfetto
2110