blob: ae9474580e6c7d20ad962ebdabcce5aa1a0698d3 [file] [log] [blame]
Lalit Maganti93b76362018-06-01 03:03:58 +01001/*
2 * Copyright (C) 2018 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
Primiano Tucci0d72a312018-08-07 14:42:45 +010017#include "src/trace_processor/proto_trace_parser.h"
Lalit Maganti93b76362018-06-01 03:03:58 +010018
Ryan Savitski717d5542019-03-18 12:00:16 +000019#include <inttypes.h>
Primiano Tucci132a34d2018-09-19 19:34:01 +010020#include <string.h>
21
Lalit Magantidf3e9262018-06-04 17:45:00 +010022#include <string>
23
Primiano Tuccid933d912018-09-04 09:15:07 +010024#include "perfetto/base/logging.h"
Primiano Tucci2c5488f2019-06-01 03:27:28 +010025#include "perfetto/ext/base/optional.h"
26#include "perfetto/ext/base/string_view.h"
27#include "perfetto/ext/base/utils.h"
28#include "perfetto/ext/traced/sys_stats_counters.h"
Primiano Tucci0d72a312018-08-07 14:42:45 +010029#include "perfetto/protozero/proto_decoder.h"
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +000030#include "src/trace_processor/args_tracker.h"
Primiano Tuccia270f012019-01-07 20:01:00 +000031#include "src/trace_processor/clock_tracker.h"
Isabelle Taylora97c5f52018-10-23 17:36:12 +010032#include "src/trace_processor/event_tracker.h"
Lalit Maganti1d915a62019-01-07 12:10:42 +000033#include "src/trace_processor/ftrace_descriptors.h"
Florian Mayer438b5ab2019-05-02 11:18:06 +010034#include "src/trace_processor/heap_profile_tracker.h"
Mikhail Khokhlovb1fe42a2019-05-23 13:58:05 +010035#include "src/trace_processor/metadata.h"
Primiano Tucci0d72a312018-08-07 14:42:45 +010036#include "src/trace_processor/process_tracker.h"
Hector Dearman947f12a2018-09-11 16:50:36 +010037#include "src/trace_processor/slice_tracker.h"
Hector Dearmanf31a7032019-03-29 10:05:09 +000038#include "src/trace_processor/syscall_tracker.h"
Lalit Magantid54d7522019-05-30 14:36:08 +010039#include "src/trace_processor/systrace_utils.h"
Primiano Tucci0d72a312018-08-07 14:42:45 +010040#include "src/trace_processor/trace_processor_context.h"
Mikhail Khokhlov85a0dd02019-05-17 14:22:28 +010041#include "src/trace_processor/variadic.h"
Primiano Tucci0d72a312018-08-07 14:42:45 +010042
Primiano Tuccie5f11682019-03-22 07:21:49 +000043#include "perfetto/common/android_log_constants.pbzero.h"
44#include "perfetto/common/trace_stats.pbzero.h"
45#include "perfetto/trace/android/android_log.pbzero.h"
Mikhail Khokhlovb1fe42a2019-05-23 13:58:05 +010046#include "perfetto/trace/chrome/chrome_benchmark_metadata.pbzero.h"
Primiano Tuccie5f11682019-03-22 07:21:49 +000047#include "perfetto/trace/clock_snapshot.pbzero.h"
48#include "perfetto/trace/ftrace/ftrace.pbzero.h"
49#include "perfetto/trace/ftrace/ftrace_event.pbzero.h"
50#include "perfetto/trace/ftrace/ftrace_stats.pbzero.h"
51#include "perfetto/trace/ftrace/generic.pbzero.h"
52#include "perfetto/trace/ftrace/kmem.pbzero.h"
53#include "perfetto/trace/ftrace/lowmemorykiller.pbzero.h"
54#include "perfetto/trace/ftrace/mm_event.pbzero.h"
55#include "perfetto/trace/ftrace/oom.pbzero.h"
56#include "perfetto/trace/ftrace/power.pbzero.h"
57#include "perfetto/trace/ftrace/raw_syscalls.pbzero.h"
58#include "perfetto/trace/ftrace/sched.pbzero.h"
59#include "perfetto/trace/ftrace/signal.pbzero.h"
60#include "perfetto/trace/ftrace/task.pbzero.h"
Eric Seckler56a007d2019-05-02 16:25:14 +010061#include "perfetto/trace/interned_data/interned_data.pbzero.h"
Primiano Tuccie5f11682019-03-22 07:21:49 +000062#include "perfetto/trace/power/battery_counters.pbzero.h"
Lalit Magantie23653a2019-03-27 17:21:42 +000063#include "perfetto/trace/power/power_rails.pbzero.h"
Primiano Tuccie5f11682019-03-22 07:21:49 +000064#include "perfetto/trace/profiling/profile_packet.pbzero.h"
65#include "perfetto/trace/ps/process_stats.pbzero.h"
66#include "perfetto/trace/ps/process_tree.pbzero.h"
67#include "perfetto/trace/sys_stats/sys_stats.pbzero.h"
Hector Dearmanf31a7032019-03-29 10:05:09 +000068#include "perfetto/trace/system_info.pbzero.h"
Primiano Tuccie5f11682019-03-22 07:21:49 +000069#include "perfetto/trace/trace.pbzero.h"
70#include "perfetto/trace/trace_packet.pbzero.h"
Eric Seckler56a007d2019-05-02 16:25:14 +010071#include "perfetto/trace/track_event/debug_annotation.pbzero.h"
72#include "perfetto/trace/track_event/task_execution.pbzero.h"
73#include "perfetto/trace/track_event/track_event.pbzero.h"
Lalit Maganti93b76362018-06-01 03:03:58 +010074
75namespace perfetto {
76namespace trace_processor {
77
Lalit Maganti1d915a62019-01-07 12:10:42 +000078namespace {
79
80using protozero::ProtoDecoder;
Lalit Maganti1d915a62019-01-07 12:10:42 +000081
82} // namespace
83
Primiano Tucci7e330292018-08-24 19:10:52 +020084ProtoTraceParser::ProtoTraceParser(TraceProcessorContext* context)
Isabelle Taylor15314ea2018-09-19 11:35:19 +010085 : context_(context),
Lalit Maganti6e9c55e2018-11-29 12:00:39 +000086 utid_name_id_(context->storage->InternString("utid")),
Lalit Maganti369ea3c2019-03-05 11:09:42 +000087 sched_wakeup_name_id_(context->storage->InternString("sched_wakeup")),
Isabelle Taylor54ce7052018-10-01 14:00:15 +010088 cpu_freq_name_id_(context->storage->InternString("cpufreq")),
Hector Dearman7b794cc2018-11-30 14:35:30 +000089 cpu_idle_name_id_(context->storage->InternString("cpuidle")),
Lalit Maganti66ed7ad2019-01-11 16:47:26 +000090 comm_name_id_(context->storage->InternString("comm")),
Isabelle Taylor54ce7052018-10-01 14:00:15 +010091 num_forks_name_id_(context->storage->InternString("num_forks")),
92 num_irq_total_name_id_(context->storage->InternString("num_irq_total")),
93 num_softirq_total_name_id_(
94 context->storage->InternString("num_softirq_total")),
95 num_irq_name_id_(context->storage->InternString("num_irq")),
96 num_softirq_name_id_(context->storage->InternString("num_softirq")),
97 cpu_times_user_ns_id_(
98 context->storage->InternString("cpu.times.user_ns")),
Primiano Tuccie5f11682019-03-22 07:21:49 +000099 cpu_times_user_nice_ns_id_(
100 context->storage->InternString("cpu.times.user_nice_ns")),
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100101 cpu_times_system_mode_ns_id_(
102 context->storage->InternString("cpu.times.system_mode_ns")),
103 cpu_times_idle_ns_id_(
104 context->storage->InternString("cpu.times.idle_ns")),
105 cpu_times_io_wait_ns_id_(
106 context->storage->InternString("cpu.times.io_wait_ns")),
107 cpu_times_irq_ns_id_(context->storage->InternString("cpu.times.irq_ns")),
108 cpu_times_softirq_ns_id_(
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100109 context->storage->InternString("cpu.times.softirq_ns")),
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000110 signal_deliver_id_(context->storage->InternString("signal_deliver")),
Primiano Tuccib86e9ca2018-12-03 20:20:11 +0100111 signal_generate_id_(context->storage->InternString("signal_generate")),
112 batt_charge_id_(context->storage->InternString("batt.charge_uah")),
113 batt_capacity_id_(context->storage->InternString("batt.capacity_pct")),
114 batt_current_id_(context->storage->InternString("batt.current_ua")),
115 batt_current_avg_id_(
Primiano Tucci44231042018-12-06 21:34:32 +0000116 context->storage->InternString("batt.current.avg_ua")),
Lalit Maganti66ed7ad2019-01-11 16:47:26 +0000117 lmk_id_(context->storage->InternString("mem.lmk")),
Primiano Tucci90cdc852018-12-21 10:29:44 +0100118 oom_score_adj_id_(context->storage->InternString("oom_score_adj")),
119 ion_total_unknown_id_(context->storage->InternString("mem.ion.unknown")),
120 ion_change_unknown_id_(
121 context->storage->InternString("mem.ion_change.unknown")) {
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100122 for (const auto& name : BuildMeminfoCounterNames()) {
123 meminfo_strs_id_.emplace_back(context->storage->InternString(name));
124 }
125 for (const auto& name : BuildVmstatCounterNames()) {
126 vmstat_strs_id_.emplace_back(context->storage->InternString(name));
127 }
Lalit Maganti6820abc2019-01-21 11:12:23 +0000128 rss_members_.emplace_back(context->storage->InternString("mem.rss.file"));
129 rss_members_.emplace_back(context->storage->InternString("mem.rss.anon"));
Lalit Maganti5a95df22019-01-24 13:28:36 +0000130 rss_members_.emplace_back(context->storage->InternString("mem.swap"));
Lalit Maganti6820abc2019-01-21 11:12:23 +0000131 rss_members_.emplace_back(context->storage->InternString("mem.rss.shmem"));
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100132 rss_members_.emplace_back(
Lalit Maganti6820abc2019-01-21 11:12:23 +0000133 context->storage->InternString("mem.rss.unknown")); // Keep this last.
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700134
Primiano Tuccie5f11682019-03-22 07:21:49 +0000135 using ProcessStats = protos::pbzero::ProcessStats;
Lalit Maganti41c98922019-01-23 19:35:58 +0000136 proc_stats_process_names_[ProcessStats::Process::kVmSizeKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700137 context->storage->InternString("mem.virt");
Lalit Maganti41c98922019-01-23 19:35:58 +0000138 proc_stats_process_names_[ProcessStats::Process::kVmRssKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700139 context->storage->InternString("mem.rss");
Lalit Maganti41c98922019-01-23 19:35:58 +0000140 proc_stats_process_names_[ProcessStats::Process::kRssAnonKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700141 context->storage->InternString("mem.rss.anon");
Lalit Maganti41c98922019-01-23 19:35:58 +0000142 proc_stats_process_names_[ProcessStats::Process::kRssFileKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700143 context->storage->InternString("mem.rss.file");
Lalit Maganti41c98922019-01-23 19:35:58 +0000144 proc_stats_process_names_[ProcessStats::Process::kRssShmemKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700145 context->storage->InternString("mem.rss.shmem");
Lalit Maganti41c98922019-01-23 19:35:58 +0000146 proc_stats_process_names_[ProcessStats::Process::kVmSwapKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700147 context->storage->InternString("mem.swap");
Lalit Maganti41c98922019-01-23 19:35:58 +0000148 proc_stats_process_names_[ProcessStats::Process::kVmLockedKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700149 context->storage->InternString("mem.locked");
Lalit Maganti41c98922019-01-23 19:35:58 +0000150 proc_stats_process_names_[ProcessStats::Process::kVmHwmKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700151 context->storage->InternString("mem.rss.watermark");
Lalit Maganti41c98922019-01-23 19:35:58 +0000152 proc_stats_process_names_[ProcessStats::Process::kOomScoreAdjFieldNumber] =
153 oom_score_adj_id_;
Lalit Magantia824c332019-01-23 17:55:58 +0000154
Hector Dearmanbd6cd472019-02-13 16:42:52 +0000155 mm_event_counter_names_ = {
156 {MmEventCounterNames(
157 context->storage->InternString("mem.mm.min_flt.count"),
158 context->storage->InternString("mem.mm.min_flt.max_lat"),
159 context->storage->InternString("mem.mm.min_flt.avg_lat")),
160 MmEventCounterNames(
161 context->storage->InternString("mem.mm.maj_flt.count"),
162 context->storage->InternString("mem.mm.maj_flt.max_lat"),
163 context->storage->InternString("mem.mm.maj_flt.avg_lat")),
164 MmEventCounterNames(
165 context->storage->InternString("mem.mm.read_io.count"),
166 context->storage->InternString("mem.mm.read_io.max_lat"),
167 context->storage->InternString("mem.mm.read_io.avg_lat")),
168 MmEventCounterNames(
169 context->storage->InternString("mem.mm.compaction.count"),
170 context->storage->InternString("mem.mm.compaction.max_lat"),
171 context->storage->InternString("mem.mm.compaction.avg_lat")),
172 MmEventCounterNames(
173 context->storage->InternString("mem.mm.reclaim.count"),
174 context->storage->InternString("mem.mm.reclaim.max_lat"),
175 context->storage->InternString("mem.mm.reclaim.avg_lat")),
176 MmEventCounterNames(
177 context->storage->InternString("mem.mm.swp_flt.count"),
178 context->storage->InternString("mem.mm.swp_flt.max_lat"),
179 context->storage->InternString("mem.mm.swp_flt.avg_lat")),
180 MmEventCounterNames(
181 context->storage->InternString("mem.mm.kern_alloc.count"),
182 context->storage->InternString("mem.mm.kern_alloc.max_lat"),
183 context->storage->InternString("mem.mm.kern_alloc.avg_lat"))}};
184
Lalit Magantid86161a2019-02-06 15:07:13 +0000185 // Build the lookup table for the strings inside ftrace events (e.g. the
186 // name of ftrace event fields and the names of their args).
187 for (size_t i = 0; i < GetDescriptorsSize(); i++) {
188 auto* descriptor = GetMessageDescriptorForId(i);
189 if (!descriptor->name) {
190 ftrace_message_strings_.emplace_back();
191 continue;
192 }
193
194 FtraceMessageStrings ftrace_strings;
195 ftrace_strings.message_name_id =
196 context->storage->InternString(descriptor->name);
197
Lalit Maganti3043fbd2019-02-07 10:21:50 +0000198 for (size_t fid = 0; fid <= descriptor->max_field_id; fid++) {
Lalit Magantid86161a2019-02-06 15:07:13 +0000199 const auto& field = descriptor->fields[fid];
200 if (!field.name)
201 continue;
202 ftrace_strings.field_name_ids[fid] =
203 context->storage->InternString(field.name);
204 }
205 ftrace_message_strings_.emplace_back(ftrace_strings);
206 }
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100207}
Lalit Maganti93b76362018-06-01 03:03:58 +0100208
Primiano Tucci0d72a312018-08-07 14:42:45 +0100209ProtoTraceParser::~ProtoTraceParser() = default;
210
Deepanjan Roy01994ca2019-04-02 11:05:34 -0700211void ProtoTraceParser::ParseTracePacket(
212 int64_t ts,
213 TraceSorter::TimestampedTracePiece ttp) {
214 PERFETTO_DCHECK(ttp.json_value == nullptr);
215 const TraceBlobView& blob = ttp.blob_view;
216
Primiano Tuccie5f11682019-03-22 07:21:49 +0000217 protos::pbzero::TracePacket::Decoder packet(blob.data(), blob.length());
Lalit Maganti93b76362018-06-01 03:03:58 +0100218
Primiano Tuccie5f11682019-03-22 07:21:49 +0000219 if (packet.has_process_tree())
220 ParseProcessTree(packet.process_tree());
221
222 if (packet.has_process_stats())
223 ParseProcessStats(ts, packet.process_stats());
224
225 if (packet.has_sys_stats())
226 ParseSysStats(ts, packet.sys_stats());
227
228 if (packet.has_battery())
229 ParseBatteryCounters(ts, packet.battery());
230
Lalit Magantie23653a2019-03-27 17:21:42 +0000231 if (packet.has_power_rails())
232 ParsePowerRails(packet.power_rails());
233
Primiano Tuccie5f11682019-03-22 07:21:49 +0000234 if (packet.has_trace_stats())
235 ParseTraceStats(packet.trace_stats());
236
237 if (packet.has_ftrace_stats())
238 ParseFtraceStats(packet.ftrace_stats());
239
240 if (packet.has_clock_snapshot())
241 ParseClockSnapshot(packet.clock_snapshot());
242
243 if (packet.has_android_log())
244 ParseAndroidLogPacket(packet.android_log());
245
246 if (packet.has_profile_packet())
Florian Mayer12c89992019-05-14 13:03:10 +0100247 ParseProfilePacket(ts, packet.profile_packet());
Primiano Tuccie5f11682019-03-22 07:21:49 +0000248
Hector Dearmanf31a7032019-03-29 10:05:09 +0000249 if (packet.has_system_info())
250 ParseSystemInfo(packet.system_info());
251
Eric Seckler56a007d2019-05-02 16:25:14 +0100252 if (packet.has_track_event()) {
253 ParseTrackEvent(ts, ttp.thread_timestamp, ttp.packet_sequence_state,
254 packet.track_event());
255 }
256
Mikhail Khokhlovb1fe42a2019-05-23 13:58:05 +0100257 if (packet.has_chrome_benchmark_metadata()) {
258 ParseChromeBenchmarkMetadata(packet.chrome_benchmark_metadata());
259 }
260
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +0000261 // TODO(lalitm): maybe move this to the flush method in the trace processor
262 // once we have it. This may reduce performance in the ArgsTracker though so
263 // needs to be handled carefully.
264 context_->args_tracker->Flush();
Primiano Tuccie5f11682019-03-22 07:21:49 +0000265 PERFETTO_DCHECK(!packet.bytes_left());
Lalit Magantidf3e9262018-06-04 17:45:00 +0100266}
267
Primiano Tuccie5f11682019-03-22 07:21:49 +0000268void ProtoTraceParser::ParseSysStats(int64_t ts, ConstBytes blob) {
269 protos::pbzero::SysStats::Decoder sys_stats(blob.data, blob.size);
270
271 for (auto it = sys_stats.meminfo(); it; ++it) {
272 protos::pbzero::SysStats::MeminfoValue::Decoder mi(it->data(), it->size());
273 auto key = static_cast<size_t>(mi.key());
274 if (PERFETTO_UNLIKELY(key >= meminfo_strs_id_.size())) {
275 PERFETTO_ELOG("MemInfo key %zu is not recognized.", key);
276 context_->storage->IncrementStats(stats::meminfo_unknown_keys);
277 continue;
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100278 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000279 // /proc/meminfo counters are in kB, convert to bytes
280 context_->event_tracker->PushCounter(
281 ts, mi.value() * 1024L, meminfo_strs_id_[key], 0, RefType::kRefNoRef);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100282 }
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100283
Primiano Tuccie5f11682019-03-22 07:21:49 +0000284 for (auto it = sys_stats.vmstat(); it; ++it) {
285 protos::pbzero::SysStats::VmstatValue::Decoder vm(it->data(), it->size());
286 auto key = static_cast<size_t>(vm.key());
287 if (PERFETTO_UNLIKELY(key >= vmstat_strs_id_.size())) {
288 PERFETTO_ELOG("VmStat key %zu is not recognized.", key);
289 context_->storage->IncrementStats(stats::vmstat_unknown_keys);
290 continue;
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100291 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000292 context_->event_tracker->PushCounter(ts, vm.value(), vmstat_strs_id_[key],
293 0, RefType::kRefNoRef);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100294 }
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100295
Primiano Tuccie5f11682019-03-22 07:21:49 +0000296 for (auto it = sys_stats.cpu_stat(); it; ++it) {
297 protos::pbzero::SysStats::CpuTimes::Decoder ct(it->data(), it->size());
298 if (PERFETTO_UNLIKELY(!ct.has_cpu_id())) {
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100299 PERFETTO_ELOG("CPU field not found in CpuTimes");
Primiano Tucci0e38a142019-01-07 20:51:09 +0000300 context_->storage->IncrementStats(stats::invalid_cpu_times);
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700301 continue;
Isabelle Taylord80932a2018-06-19 17:00:47 +0100302 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000303 context_->event_tracker->PushCounter(ts, ct.user_ns(),
304 cpu_times_user_ns_id_, ct.cpu_id(),
305 RefType::kRefCpuId);
306 context_->event_tracker->PushCounter(ts, ct.user_ice_ns(),
307 cpu_times_user_nice_ns_id_,
308 ct.cpu_id(), RefType::kRefCpuId);
309 context_->event_tracker->PushCounter(ts, ct.system_mode_ns(),
310 cpu_times_system_mode_ns_id_,
311 ct.cpu_id(), RefType::kRefCpuId);
312 context_->event_tracker->PushCounter(ts, ct.idle_ns(),
313 cpu_times_idle_ns_id_, ct.cpu_id(),
314 RefType::kRefCpuId);
315 context_->event_tracker->PushCounter(ts, ct.io_wait_ns(),
316 cpu_times_io_wait_ns_id_, ct.cpu_id(),
317 RefType::kRefCpuId);
318 context_->event_tracker->PushCounter(ts, ct.irq_ns(), cpu_times_irq_ns_id_,
319 ct.cpu_id(), RefType::kRefCpuId);
320 context_->event_tracker->PushCounter(ts, ct.softirq_ns(),
321 cpu_times_softirq_ns_id_, ct.cpu_id(),
322 RefType::kRefCpuId);
Isabelle Taylord80932a2018-06-19 17:00:47 +0100323 }
Isabelle Taylord80932a2018-06-19 17:00:47 +0100324
Primiano Tuccie5f11682019-03-22 07:21:49 +0000325 for (auto it = sys_stats.num_irq(); it; ++it) {
326 protos::pbzero::SysStats::InterruptCount::Decoder ic(it->data(),
327 it->size());
328 context_->event_tracker->PushCounter(ts, ic.count(), num_irq_name_id_,
329 ic.irq(), RefType::kRefIrq);
330 }
331
332 for (auto it = sys_stats.num_softirq(); it; ++it) {
333 protos::pbzero::SysStats::InterruptCount::Decoder ic(it->data(),
334 it->size());
335 context_->event_tracker->PushCounter(ts, ic.count(), num_softirq_name_id_,
336 ic.irq(), RefType::kRefSoftIrq);
337 }
338
339 if (sys_stats.has_num_forks()) {
340 context_->event_tracker->PushCounter(
341 ts, sys_stats.num_forks(), num_forks_name_id_, 0, RefType::kRefNoRef);
342 }
343
344 if (sys_stats.has_num_irq_total()) {
345 context_->event_tracker->PushCounter(ts, sys_stats.num_irq_total(),
346 num_irq_total_name_id_, 0,
347 RefType::kRefNoRef);
348 }
349
350 if (sys_stats.has_num_softirq_total()) {
351 context_->event_tracker->PushCounter(ts, sys_stats.num_softirq_total(),
352 num_softirq_total_name_id_, 0,
353 RefType::kRefNoRef);
354 }
Isabelle Taylord80932a2018-06-19 17:00:47 +0100355}
356
Primiano Tuccie5f11682019-03-22 07:21:49 +0000357void ProtoTraceParser::ParseProcessTree(ConstBytes blob) {
358 protos::pbzero::ProcessTree::Decoder ps(blob.data, blob.size);
Primiano Tuccid933d912018-09-04 09:15:07 +0100359
Primiano Tuccie5f11682019-03-22 07:21:49 +0000360 for (auto it = ps.processes(); it; ++it) {
361 protos::pbzero::ProcessTree::Process::Decoder proc(it->data(), it->size());
362 if (!proc.has_cmdline())
363 continue;
364 auto pid = static_cast<uint32_t>(proc.pid());
365 auto ppid = static_cast<uint32_t>(proc.ppid());
Primiano Tuccid933d912018-09-04 09:15:07 +0100366
Primiano Tuccie5f11682019-03-22 07:21:49 +0000367 context_->process_tracker->UpdateProcess(pid, ppid,
368 proc.cmdline()->as_string());
369 }
370
371 for (auto it = ps.threads(); it; ++it) {
372 protos::pbzero::ProcessTree::Thread::Decoder thd(it->data(), it->size());
373 auto tid = static_cast<uint32_t>(thd.tid());
374 auto tgid = static_cast<uint32_t>(thd.tgid());
375 context_->process_tracker->UpdateThread(tid, tgid);
376 }
377}
378
379void ProtoTraceParser::ParseProcessStats(int64_t ts, ConstBytes blob) {
380 protos::pbzero::ProcessStats::Decoder stats(blob.data, blob.size);
381 const auto kOomScoreAdjFieldNumber =
382 protos::pbzero::ProcessStats::Process::kOomScoreAdjFieldNumber;
383 for (auto it = stats.processes(); it; ++it) {
384 // Maps a process counter field it to its value.
385 // E.g., 4 := 1024 -> "mem.rss.anon" := 1024.
386 std::array<int64_t, kProcStatsProcessSize> counter_values{};
387 std::array<bool, kProcStatsProcessSize> has_counter{};
388
389 ProtoDecoder proc(it->data(), it->size());
390 uint32_t pid = 0;
391 for (auto fld = proc.ReadField(); fld.valid(); fld = proc.ReadField()) {
392 if (fld.id() == protos::pbzero::ProcessStats::Process::kPidFieldNumber) {
Isabelle Taylord80932a2018-06-19 17:00:47 +0100393 pid = fld.as_uint32();
Primiano Tuccie5f11682019-03-22 07:21:49 +0000394 continue;
395 }
396 bool is_counter_field = fld.id() < proc_stats_process_names_.size() &&
397 proc_stats_process_names_[fld.id()] != 0;
398 if (is_counter_field) {
399 // Memory counters are in KB, keep values in bytes in the trace
400 // processor.
401 counter_values[fld.id()] = fld.id() == kOomScoreAdjFieldNumber
402 ? fld.as_int64()
403 : fld.as_int64() * 1024;
404 has_counter[fld.id()] = true;
405 } else {
406 context_->storage->IncrementStats(stats::proc_stat_unknown_counters);
407 }
408 }
409
410 // Skip field_id 0 (invalid) and 1 (pid).
411 for (size_t field_id = 2; field_id < counter_values.size(); field_id++) {
412 if (!has_counter[field_id])
413 continue;
414
415 // Lookup the interned string id from the field name using the
416 // pre-cached |proc_stats_process_names_| map.
417 StringId name = proc_stats_process_names_[field_id];
418 int64_t value = counter_values[field_id];
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100419 UniquePid upid = context_->process_tracker->GetOrCreateProcess(pid);
Primiano Tuccie5f11682019-03-22 07:21:49 +0000420 context_->event_tracker->PushCounter(ts, value, name, upid,
421 RefType::kRefUpid);
Isabelle Taylord80932a2018-06-19 17:00:47 +0100422 }
423 }
Isabelle Taylord80932a2018-06-19 17:00:47 +0100424}
425
Deepanjan Roy01994ca2019-04-02 11:05:34 -0700426void ProtoTraceParser::ParseFtracePacket(
427 uint32_t cpu,
428 int64_t ts,
429 TraceSorter::TimestampedTracePiece ttp) {
430 PERFETTO_DCHECK(ttp.json_value == nullptr);
431 const TraceBlobView& ftrace = ttp.blob_view;
432
Primiano Tuccid933d912018-09-04 09:15:07 +0100433 ProtoDecoder decoder(ftrace.data(), ftrace.length());
Lalit Maganti1d915a62019-01-07 12:10:42 +0000434 uint64_t raw_pid = 0;
Primiano Tuccic1678872019-03-20 11:30:54 +0000435 if (auto pid_field =
Primiano Tuccie5f11682019-03-22 07:21:49 +0000436 decoder.FindField(protos::pbzero::FtraceEvent::kPidFieldNumber)) {
Primiano Tuccic1678872019-03-20 11:30:54 +0000437 raw_pid = pid_field.as_uint64();
438 } else {
Lalit Maganti1d915a62019-01-07 12:10:42 +0000439 PERFETTO_ELOG("Pid field not found in ftrace packet");
440 return;
441 }
442 uint32_t pid = static_cast<uint32_t>(raw_pid);
443
Primiano Tuccic1678872019-03-20 11:30:54 +0000444 for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
Lalit Maganti1d915a62019-01-07 12:10:42 +0000445 bool is_metadata_field =
Primiano Tuccie5f11682019-03-22 07:21:49 +0000446 fld.id() == protos::pbzero::FtraceEvent::kPidFieldNumber ||
447 fld.id() == protos::pbzero::FtraceEvent::kTimestampFieldNumber;
Lalit Maganti1d915a62019-01-07 12:10:42 +0000448 if (is_metadata_field)
449 continue;
450
Primiano Tuccie5f11682019-03-22 07:21:49 +0000451 ConstBytes data = fld.as_bytes();
452 if (fld.id() == protos::pbzero::FtraceEvent::kGenericFieldNumber) {
453 ParseGenericFtrace(ts, cpu, pid, data);
454 } else if (fld.id() !=
455 protos::pbzero::FtraceEvent::kSchedSwitchFieldNumber) {
456 ParseTypedFtraceToRaw(fld.id(), ts, cpu, pid, data);
Lalit Maganti1d915a62019-01-07 12:10:42 +0000457 }
458
Primiano Tuccic1678872019-03-20 11:30:54 +0000459 switch (fld.id()) {
Primiano Tuccie5f11682019-03-22 07:21:49 +0000460 case protos::pbzero::FtraceEvent::kSchedSwitchFieldNumber: {
461 ParseSchedSwitch(cpu, ts, data);
Lalit Magantidf3e9262018-06-04 17:45:00 +0100462 break;
Primiano Tuccid933d912018-09-04 09:15:07 +0100463 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000464 case protos::pbzero::FtraceEvent::kSchedWakeupFieldNumber: {
465 ParseSchedWakeup(ts, data);
Lalit Maganti369ea3c2019-03-05 11:09:42 +0000466 break;
467 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000468 case protos::pbzero::FtraceEvent::kCpuFrequencyFieldNumber: {
469 ParseCpuFreq(ts, data);
Isabelle Taylor14674d42018-09-07 11:33:11 +0100470 break;
471 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000472 case protos::pbzero::FtraceEvent::kCpuIdleFieldNumber: {
473 ParseCpuIdle(ts, data);
Hector Dearman7b794cc2018-11-30 14:35:30 +0000474 break;
475 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000476 case protos::pbzero::FtraceEvent::kPrintFieldNumber: {
477 ParsePrint(cpu, ts, pid, data);
Hector Dearman947f12a2018-09-11 16:50:36 +0100478 break;
479 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000480 case protos::pbzero::FtraceEvent::kRssStatFieldNumber: {
481 ParseRssStat(ts, pid, data);
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100482 break;
483 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000484 case protos::pbzero::FtraceEvent::kIonHeapGrowFieldNumber: {
485 ParseIonHeapGrowOrShrink(ts, pid, data, true);
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100486 break;
487 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000488 case protos::pbzero::FtraceEvent::kIonHeapShrinkFieldNumber: {
489 ParseIonHeapGrowOrShrink(ts, pid, data, false);
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100490 break;
491 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000492 case protos::pbzero::FtraceEvent::kSignalGenerateFieldNumber: {
493 ParseSignalGenerate(ts, data);
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000494 break;
495 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000496 case protos::pbzero::FtraceEvent::kSignalDeliverFieldNumber: {
497 ParseSignalDeliver(ts, pid, data);
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000498 break;
499 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000500 case protos::pbzero::FtraceEvent::kLowmemoryKillFieldNumber: {
501 ParseLowmemoryKill(ts, data);
Lalit Maganti66ed7ad2019-01-11 16:47:26 +0000502 break;
503 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000504 case protos::pbzero::FtraceEvent::kOomScoreAdjUpdateFieldNumber: {
505 ParseOOMScoreAdjUpdate(ts, data);
Primiano Tucci44231042018-12-06 21:34:32 +0000506 break;
507 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000508 case protos::pbzero::FtraceEvent::kMmEventRecordFieldNumber: {
509 ParseMmEventRecord(ts, pid, data);
Lalit Magantia824c332019-01-23 17:55:58 +0000510 break;
511 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000512 case protos::pbzero::FtraceEvent::kSysEnterFieldNumber: {
513 ParseSysEvent(ts, pid, true, data);
Hector Dearmanbd6cd472019-02-13 16:42:52 +0000514 break;
515 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000516 case protos::pbzero::FtraceEvent::kSysExitFieldNumber: {
517 ParseSysEvent(ts, pid, false, data);
Hector Dearmanbd6cd472019-02-13 16:42:52 +0000518 break;
519 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000520 case protos::pbzero::FtraceEvent::kTaskNewtaskFieldNumber: {
521 ParseTaskNewTask(ts, pid, data);
Primiano Tucci711de1f2019-03-04 11:11:33 +0000522 break;
523 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000524 case protos::pbzero::FtraceEvent::kTaskRenameFieldNumber: {
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100525 ParseTaskRename(data);
Primiano Tucci711de1f2019-03-04 11:11:33 +0000526 break;
527 }
Lalit Magantidf3e9262018-06-04 17:45:00 +0100528 default:
529 break;
530 }
531 }
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +0000532 // TODO(lalitm): maybe move this to the flush method in the trace processor
533 // once we have it. This may reduce performance in the ArgsTracker though so
534 // needs to be handled carefully.
535 context_->args_tracker->Flush();
536
Primiano Tuccic1678872019-03-20 11:30:54 +0000537 PERFETTO_DCHECK(!decoder.bytes_left());
Lalit Magantidf3e9262018-06-04 17:45:00 +0100538}
539
Primiano Tuccie5f11682019-03-22 07:21:49 +0000540void ProtoTraceParser::ParseSignalDeliver(int64_t ts,
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000541 uint32_t pid,
Primiano Tuccie5f11682019-03-22 07:21:49 +0000542 ConstBytes blob) {
543 protos::pbzero::SignalDeliverFtraceEvent::Decoder sig(blob.data, blob.size);
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100544 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
Lalit Maganti521d97b2019-04-29 13:47:03 +0100545 context_->event_tracker->PushInstant(ts, signal_deliver_id_, sig.sig(), utid,
546 RefType::kRefUtid);
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000547}
548
Isabelle Taylor0996dbf2018-11-07 11:33:38 +0000549// This event has both the pid of the thread that sent the signal and the
550// destination of the signal. Currently storing the pid of the destination.
Primiano Tuccie5f11682019-03-22 07:21:49 +0000551void ProtoTraceParser::ParseSignalGenerate(int64_t ts, ConstBytes blob) {
552 protos::pbzero::SignalGenerateFtraceEvent::Decoder sig(blob.data, blob.size);
553
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100554 UniqueTid utid = context_->process_tracker->GetOrCreateThread(
555 static_cast<uint32_t>(sig.pid()));
Lalit Maganti521d97b2019-04-29 13:47:03 +0100556 context_->event_tracker->PushInstant(ts, signal_generate_id_, sig.sig(), utid,
557 RefType::kRefUtid);
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000558}
559
Primiano Tuccie5f11682019-03-22 07:21:49 +0000560void ProtoTraceParser::ParseLowmemoryKill(int64_t ts, ConstBytes blob) {
Isabelle Taylor0996dbf2018-11-07 11:33:38 +0000561 // TODO(taylori): Store the pagecache_size, pagecache_limit and free fields
562 // in an args table
Primiano Tuccie5f11682019-03-22 07:21:49 +0000563 protos::pbzero::LowmemoryKillFtraceEvent::Decoder lmk(blob.data, blob.size);
Lalit Maganti66ed7ad2019-01-11 16:47:26 +0000564
Primiano Tuccie5f11682019-03-22 07:21:49 +0000565 // Store the pid of the event that is lmk-ed.
Lalit Maganti521d97b2019-04-29 13:47:03 +0100566 auto pid = static_cast<uint32_t>(lmk.pid());
567 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
568 auto row_id = context_->event_tracker->PushInstant(ts, lmk_id_, 0, utid,
569 RefType::kRefUtid, true);
Lalit Maganti66ed7ad2019-01-11 16:47:26 +0000570
571 // Store the comm as an arg.
Lalit Magantid63ec5a2019-03-28 13:55:56 +0000572 auto comm_id = context_->storage->InternString(
573 lmk.has_comm() ? lmk.comm() : base::StringView());
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +0000574 context_->args_tracker->AddArg(row_id, comm_name_id_, comm_name_id_,
575 Variadic::String(comm_id));
Isabelle Taylor0996dbf2018-11-07 11:33:38 +0000576}
577
Primiano Tuccie5f11682019-03-22 07:21:49 +0000578void ProtoTraceParser::ParseRssStat(int64_t ts, uint32_t pid, ConstBytes blob) {
579 protos::pbzero::RssStatFtraceEvent::Decoder rss(blob.data, blob.size);
Primiano Tuccibc560992018-12-06 19:11:45 +0000580 const auto kRssStatUnknown = static_cast<uint32_t>(rss_members_.size()) - 1;
Primiano Tuccie5f11682019-03-22 07:21:49 +0000581 auto member = static_cast<uint32_t>(rss.member());
582 int64_t size = rss.size();
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700583 if (member >= rss_members_.size()) {
Primiano Tucci0e38a142019-01-07 20:51:09 +0000584 context_->storage->IncrementStats(stats::rss_stat_unknown_keys);
Primiano Tuccibc560992018-12-06 19:11:45 +0000585 member = kRssStatUnknown;
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700586 }
Lalit Maganti6d2edf62018-11-08 16:36:35 +0000587
Ioannis Ilkos81bd0ea2019-02-14 15:16:26 +0000588 if (size >= 0) {
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100589 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
Primiano Tuccie5f11682019-03-22 07:21:49 +0000590 context_->event_tracker->PushCounter(ts, size, rss_members_[member], utid,
Lalit Maganti521d97b2019-04-29 13:47:03 +0100591 RefType::kRefUtid, true);
Ioannis Ilkos81bd0ea2019-02-14 15:16:26 +0000592 } else {
593 context_->storage->IncrementStats(stats::rss_stat_negative_size);
594 }
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100595}
596
Primiano Tuccie5f11682019-03-22 07:21:49 +0000597void ProtoTraceParser::ParseIonHeapGrowOrShrink(int64_t ts,
Primiano Tucci90cdc852018-12-21 10:29:44 +0100598 uint32_t pid,
Primiano Tuccie5f11682019-03-22 07:21:49 +0000599 ConstBytes blob,
Primiano Tucci90cdc852018-12-21 10:29:44 +0100600 bool grow) {
Primiano Tuccie5f11682019-03-22 07:21:49 +0000601 protos::pbzero::IonHeapGrowFtraceEvent::Decoder ion(blob.data, blob.size);
Primiano Tuccie5f11682019-03-22 07:21:49 +0000602 int64_t change_bytes = static_cast<int64_t>(ion.len()) * (grow ? 1 : -1);
Ioannis Ilkosd4efb702019-05-07 14:24:49 +0100603 // The total_allocated ftrace event reports the value before the
604 // atomic_long_add / sub takes place.
605 int64_t total_bytes = ion.total_allocated() + change_bytes;
Primiano Tucci90cdc852018-12-21 10:29:44 +0100606 StringId global_name_id = ion_total_unknown_id_;
607 StringId change_name_id = ion_change_unknown_id_;
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100608
Primiano Tuccie5f11682019-03-22 07:21:49 +0000609 if (ion.has_heap_name()) {
610 char counter_name[255];
611 base::StringView heap_name = ion.heap_name();
612 snprintf(counter_name, sizeof(counter_name), "mem.ion.%.*s",
613 int(heap_name.size()), heap_name.data());
614 global_name_id = context_->storage->InternString(counter_name);
615 snprintf(counter_name, sizeof(counter_name), "mem.ion_change.%.*s",
616 int(heap_name.size()), heap_name.data());
617 change_name_id = context_->storage->InternString(counter_name);
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100618 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000619
Primiano Tucci90cdc852018-12-21 10:29:44 +0100620 // Push the global counter.
Primiano Tuccie5f11682019-03-22 07:21:49 +0000621 context_->event_tracker->PushCounter(ts, total_bytes, global_name_id, 0,
622 RefType::kRefNoRef);
Primiano Tucci90cdc852018-12-21 10:29:44 +0100623
624 // Push the change counter.
625 // TODO(b/121331269): these should really be instant events. For now we
Primiano Tuccicd37b4d2018-12-21 16:33:32 +0100626 // manually reset them to 0 after 1ns.
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100627 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
Primiano Tuccie5f11682019-03-22 07:21:49 +0000628 context_->event_tracker->PushCounter(ts, change_bytes, change_name_id, utid,
Primiano Tuccicd37b4d2018-12-21 16:33:32 +0100629 RefType::kRefUtid);
Primiano Tuccie5f11682019-03-22 07:21:49 +0000630 context_->event_tracker->PushCounter(ts + 1, 0, change_name_id, utid,
631 RefType::kRefUtid);
Primiano Tucci90cdc852018-12-21 10:29:44 +0100632
633 // We are reusing the same function for ion_heap_grow and ion_heap_shrink.
634 // It is fine as the arguments are the same, but we need to be sure that the
635 // protobuf field id for both are the same.
636 static_assert(
Primiano Tuccie5f11682019-03-22 07:21:49 +0000637 static_cast<int>(
638 protos::pbzero::IonHeapGrowFtraceEvent::kTotalAllocatedFieldNumber) ==
639 static_cast<int>(protos::pbzero::IonHeapShrinkFtraceEvent::
640 kTotalAllocatedFieldNumber) &&
641 static_cast<int>(
642 protos::pbzero::IonHeapGrowFtraceEvent::kLenFieldNumber) ==
643 static_cast<int>(
644 protos::pbzero::IonHeapShrinkFtraceEvent::kLenFieldNumber) &&
645 static_cast<int>(
646 protos::pbzero::IonHeapGrowFtraceEvent::kHeapNameFieldNumber) ==
647 static_cast<int>(protos::pbzero::IonHeapShrinkFtraceEvent::
648 kHeapNameFieldNumber),
649 "ION field mismatch");
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100650}
651
Primiano Tuccie5f11682019-03-22 07:21:49 +0000652void ProtoTraceParser::ParseCpuFreq(int64_t ts, ConstBytes blob) {
653 protos::pbzero::CpuFrequencyFtraceEvent::Decoder freq(blob.data, blob.size);
654 uint32_t cpu = freq.cpu_id();
655 uint32_t new_freq = freq.state();
656 context_->event_tracker->PushCounter(ts, new_freq, cpu_freq_name_id_, cpu,
657 RefType::kRefCpuId);
Isabelle Taylor14674d42018-09-07 11:33:11 +0100658}
659
Primiano Tuccie5f11682019-03-22 07:21:49 +0000660void ProtoTraceParser::ParseCpuIdle(int64_t ts, ConstBytes blob) {
661 protos::pbzero::CpuIdleFtraceEvent::Decoder idle(blob.data, blob.size);
662 uint32_t cpu = idle.cpu_id();
663 uint32_t new_state = idle.state();
664 context_->event_tracker->PushCounter(ts, new_state, cpu_idle_name_id_, cpu,
665 RefType::kRefCpuId);
Hector Dearman7b794cc2018-11-30 14:35:30 +0000666}
667
Primiano Tuccie5f11682019-03-22 07:21:49 +0000668PERFETTO_ALWAYS_INLINE
Primiano Tucci7e330292018-08-24 19:10:52 +0200669void ProtoTraceParser::ParseSchedSwitch(uint32_t cpu,
Primiano Tuccie5f11682019-03-22 07:21:49 +0000670 int64_t ts,
671 ConstBytes blob) {
672 protos::pbzero::SchedSwitchFtraceEvent::Decoder ss(blob.data, blob.size);
673 uint32_t prev_pid = static_cast<uint32_t>(ss.prev_pid());
674 uint32_t next_pid = static_cast<uint32_t>(ss.next_pid());
675 context_->event_tracker->PushSchedSwitch(
676 cpu, ts, prev_pid, ss.prev_comm(), ss.prev_prio(), ss.prev_state(),
677 next_pid, ss.next_comm(), ss.next_prio());
Lalit Magantidf3e9262018-06-04 17:45:00 +0100678}
679
Primiano Tuccie5f11682019-03-22 07:21:49 +0000680void ProtoTraceParser::ParseSchedWakeup(int64_t ts, ConstBytes blob) {
681 protos::pbzero::SchedWakeupFtraceEvent::Decoder sw(blob.data, blob.size);
682 uint32_t wakee_pid = static_cast<uint32_t>(sw.pid());
683 StringId name_id = context_->storage->InternString(sw.comm());
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100684 auto utid = context_->process_tracker->UpdateThreadName(wakee_pid, name_id);
Lalit Maganti521d97b2019-04-29 13:47:03 +0100685 context_->event_tracker->PushInstant(ts, sched_wakeup_name_id_, 0 /* value */,
686 utid, RefType::kRefUtid);
Lalit Maganti369ea3c2019-03-05 11:09:42 +0000687}
688
Primiano Tuccie5f11682019-03-22 07:21:49 +0000689void ProtoTraceParser::ParseTaskNewTask(int64_t ts,
Primiano Tucci711de1f2019-03-04 11:11:33 +0000690 uint32_t source_tid,
Primiano Tuccie5f11682019-03-22 07:21:49 +0000691 ConstBytes blob) {
692 protos::pbzero::TaskNewtaskFtraceEvent::Decoder evt(blob.data, blob.size);
693 uint32_t clone_flags = static_cast<uint32_t>(evt.clone_flags());
694 uint32_t new_tid = static_cast<uint32_t>(evt.pid());
695 StringId new_comm = context_->storage->InternString(evt.comm());
Primiano Tucci711de1f2019-03-04 11:11:33 +0000696 auto* proc_tracker = context_->process_tracker.get();
697
698 // task_newtask is raised both in the case of a new process creation (fork()
699 // family) and thread creation (clone(CLONE_THREAD, ...)).
700 static const uint32_t kCloneThread = 0x00010000; // From kernel's sched.h.
701 if ((clone_flags & kCloneThread) == 0) {
702 // This is a plain-old fork() or equivalent.
Primiano Tuccie5f11682019-03-22 07:21:49 +0000703 proc_tracker->StartNewProcess(ts, new_tid);
Primiano Tucci711de1f2019-03-04 11:11:33 +0000704 return;
705 }
706
707 // This is a pthread_create or similar. Bind the two threads together, so
708 // they get resolved to the same process.
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100709 auto source_utid = proc_tracker->GetOrCreateThread(source_tid);
Primiano Tuccie5f11682019-03-22 07:21:49 +0000710 auto new_utid = proc_tracker->StartNewThread(ts, new_tid, new_comm);
Primiano Tucci711de1f2019-03-04 11:11:33 +0000711 proc_tracker->AssociateThreads(source_utid, new_utid);
712}
713
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100714void ProtoTraceParser::ParseTaskRename(ConstBytes blob) {
Primiano Tuccie5f11682019-03-22 07:21:49 +0000715 protos::pbzero::TaskRenameFtraceEvent::Decoder evt(blob.data, blob.size);
716 uint32_t tid = static_cast<uint32_t>(evt.pid());
717 StringId comm = context_->storage->InternString(evt.newcomm());
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100718 context_->process_tracker->UpdateThreadName(tid, comm);
Primiano Tucci711de1f2019-03-04 11:11:33 +0000719}
720
Hector Dearman947f12a2018-09-11 16:50:36 +0100721void ProtoTraceParser::ParsePrint(uint32_t,
Primiano Tuccie5f11682019-03-22 07:21:49 +0000722 int64_t ts,
Lalit Magantide6267f2018-11-08 12:35:34 +0000723 uint32_t pid,
Primiano Tuccie5f11682019-03-22 07:21:49 +0000724 ConstBytes blob) {
725 protos::pbzero::PrintFtraceEvent::Decoder evt(blob.data, blob.size);
Lalit Magantid54d7522019-05-30 14:36:08 +0100726 systrace_utils::SystraceTracePoint point{};
Ioannis Ilkos26517c82019-05-02 13:13:08 +0100727 auto r = ParseSystraceTracePoint(evt.buf(), &point);
Lalit Magantid54d7522019-05-30 14:36:08 +0100728 if (r != systrace_utils::SystraceParseResult::kSuccess) {
729 if (r == systrace_utils::SystraceParseResult::kFailure) {
Ioannis Ilkos26517c82019-05-02 13:13:08 +0100730 context_->storage->IncrementStats(stats::systrace_parse_failure);
731 }
Hector Dearman947f12a2018-09-11 16:50:36 +0100732 return;
Lalit Maganti415532f2019-04-03 15:51:08 +0100733 }
Hector Dearman947f12a2018-09-11 16:50:36 +0100734
Hector Dearman947f12a2018-09-11 16:50:36 +0100735 switch (point.phase) {
736 case 'B': {
737 StringId name_id = context_->storage->InternString(point.name);
Primiano Tuccie5f11682019-03-22 07:21:49 +0000738 context_->slice_tracker->BeginAndroid(ts, pid, point.tgid, 0 /*cat_id*/,
739 name_id);
Hector Dearman947f12a2018-09-11 16:50:36 +0100740 break;
741 }
742
743 case 'E': {
Primiano Tuccie5f11682019-03-22 07:21:49 +0000744 context_->slice_tracker->EndAndroid(ts, pid, point.tgid);
Hector Dearman947f12a2018-09-11 16:50:36 +0100745 break;
746 }
Isabelle Taylor31e04402018-09-19 12:13:25 +0100747
748 case 'C': {
Lalit Maganti94c522b2019-01-15 00:03:15 +0000749 // LMK events from userspace are hacked as counter events with the "value"
750 // of the counter representing the pid of the killed process which is
751 // reset to 0 once the kill is complete.
752 // Homogenise this with kernel LMK events as an instant event, ignoring
753 // the resets to 0.
754 if (point.name == "kill_one_process") {
755 auto killed_pid = static_cast<uint32_t>(point.value);
756 if (killed_pid != 0) {
757 UniquePid killed_upid =
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100758 context_->process_tracker->GetOrCreateProcess(killed_pid);
Lalit Maganti521d97b2019-04-29 13:47:03 +0100759 context_->event_tracker->PushInstant(ts, lmk_id_, 0, killed_upid,
760 RefType::kRefUpid);
Lalit Maganti94c522b2019-01-15 00:03:15 +0000761 }
Hector Dearman8caa2fc2019-01-29 13:56:30 +0000762 // TODO(lalitm): we should not add LMK events to the counters table
Lalit Maganti94c522b2019-01-15 00:03:15 +0000763 // once the UI has support for displaying instants.
764 }
Hector Dearman8caa2fc2019-01-29 13:56:30 +0000765 // This is per upid on purpose. Some counters are pushed from arbitrary
766 // threads but are really per process.
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100767 UniquePid upid =
768 context_->process_tracker->GetOrCreateProcess(point.tgid);
Isabelle Taylor31e04402018-09-19 12:13:25 +0100769 StringId name_id = context_->storage->InternString(point.name);
Primiano Tuccie5f11682019-03-22 07:21:49 +0000770 context_->event_tracker->PushCounter(ts, point.value, name_id, upid,
771 RefType::kRefUpid);
Isabelle Taylor31e04402018-09-19 12:13:25 +0100772 }
Hector Dearman947f12a2018-09-11 16:50:36 +0100773 }
Hector Dearman947f12a2018-09-11 16:50:36 +0100774}
775
Primiano Tuccie5f11682019-03-22 07:21:49 +0000776void ProtoTraceParser::ParseBatteryCounters(int64_t ts, ConstBytes blob) {
777 protos::pbzero::BatteryCounters::Decoder evt(blob.data, blob.size);
778 if (evt.has_charge_counter_uah()) {
779 context_->event_tracker->PushCounter(
780 ts, evt.charge_counter_uah(), batt_charge_id_, 0, RefType::kRefNoRef);
Primiano Tuccib86e9ca2018-12-03 20:20:11 +0100781 }
Primiano Tuccie5f11682019-03-22 07:21:49 +0000782 if (evt.has_capacity_percent()) {
783 context_->event_tracker->PushCounter(
784 ts, static_cast<double>(evt.capacity_percent()), batt_capacity_id_, 0,
785 RefType::kRefNoRef);
786 }
787 if (evt.has_current_ua()) {
788 context_->event_tracker->PushCounter(ts, evt.current_ua(), batt_current_id_,
789 0, RefType::kRefNoRef);
790 }
791 if (evt.has_current_avg_ua()) {
792 context_->event_tracker->PushCounter(
793 ts, evt.current_avg_ua(), batt_current_avg_id_, 0, RefType::kRefNoRef);
794 }
Primiano Tuccib86e9ca2018-12-03 20:20:11 +0100795}
796
Lalit Magantie23653a2019-03-27 17:21:42 +0000797void ProtoTraceParser::ParsePowerRails(ConstBytes blob) {
798 protos::pbzero::PowerRails::Decoder evt(blob.data, blob.size);
799 if (evt.has_rail_descriptor()) {
800 for (auto it = evt.rail_descriptor(); it; ++it) {
801 protos::pbzero::PowerRails::RailDescriptor::Decoder desc(it->data(),
802 it->size());
Ryan Savitski2ee3f972019-04-02 15:16:38 +0100803 uint32_t idx = desc.index();
804 if (PERFETTO_UNLIKELY(idx > 256)) {
805 PERFETTO_DLOG("Skipping excessively large power_rail index %" PRIu32,
806 idx);
807 continue;
808 }
Lalit Magantie23653a2019-03-27 17:21:42 +0000809 if (power_rails_strs_id_.size() <= idx)
810 power_rails_strs_id_.resize(idx + 1);
811 char counter_name[255];
812 snprintf(counter_name, sizeof(counter_name), "power.%.*s_uws",
813 int(desc.rail_name().size), desc.rail_name().data);
814 power_rails_strs_id_[idx] = context_->storage->InternString(counter_name);
815 }
816 }
817
818 if (evt.has_energy_data()) {
819 for (auto it = evt.energy_data(); it; ++it) {
820 protos::pbzero::PowerRails::EnergyData::Decoder desc(it->data(),
821 it->size());
822 if (desc.index() < power_rails_strs_id_.size()) {
823 int64_t ts = static_cast<int64_t>(desc.timestamp_ms()) * 1000000;
824 context_->event_tracker->PushCounter(ts, desc.energy(),
825 power_rails_strs_id_[desc.index()],
826 0, RefType::kRefNoRef);
827 } else {
828 context_->storage->IncrementStats(stats::power_rail_unknown_index);
829 }
830 }
831 }
832}
833
Primiano Tuccie5f11682019-03-22 07:21:49 +0000834void ProtoTraceParser::ParseOOMScoreAdjUpdate(int64_t ts, ConstBytes blob) {
835 protos::pbzero::OomScoreAdjUpdateFtraceEvent::Decoder evt(blob.data,
836 blob.size);
837 // The int16_t static cast is because older version of the on-device tracer
838 // had a bug on negative varint encoding (b/120618641).
839 int16_t oom_adj = static_cast<int16_t>(evt.oom_score_adj());
Ioannis Ilkosc8dd9b42019-05-08 22:41:39 +0100840 uint32_t tid = static_cast<uint32_t>(evt.pid());
841 UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
842 context_->event_tracker->PushCounter(ts, oom_adj, oom_score_adj_id_, utid,
843 RefType::kRefUtid, true);
Primiano Tucci44231042018-12-06 21:34:32 +0000844}
845
Primiano Tuccie5f11682019-03-22 07:21:49 +0000846void ProtoTraceParser::ParseMmEventRecord(int64_t ts,
847 uint32_t pid,
848 ConstBytes blob) {
849 protos::pbzero::MmEventRecordFtraceEvent::Decoder evt(blob.data, blob.size);
850 uint32_t type = evt.type();
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100851 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
Primiano Tuccie5f11682019-03-22 07:21:49 +0000852
Lalit Magantia824c332019-01-23 17:55:58 +0000853 if (type >= mm_event_counter_names_.size()) {
854 context_->storage->IncrementStats(stats::mm_unknown_type);
855 return;
856 }
857
858 const auto& counter_names = mm_event_counter_names_[type];
Primiano Tuccie5f11682019-03-22 07:21:49 +0000859 context_->event_tracker->PushCounter(ts, evt.count(), counter_names.count,
Lalit Maganti521d97b2019-04-29 13:47:03 +0100860 utid, RefType::kRefUtid, true);
Primiano Tuccie5f11682019-03-22 07:21:49 +0000861 context_->event_tracker->PushCounter(ts, evt.max_lat(), counter_names.max_lat,
Lalit Maganti521d97b2019-04-29 13:47:03 +0100862 utid, RefType::kRefUtid, true);
Primiano Tuccie5f11682019-03-22 07:21:49 +0000863 context_->event_tracker->PushCounter(ts, evt.avg_lat(), counter_names.avg_lat,
Lalit Maganti521d97b2019-04-29 13:47:03 +0100864 utid, RefType::kRefUtid, true);
Lalit Magantia824c332019-01-23 17:55:58 +0000865}
866
Hector Dearmanbd6cd472019-02-13 16:42:52 +0000867void ProtoTraceParser::ParseSysEvent(int64_t ts,
868 uint32_t pid,
869 bool is_enter,
Primiano Tuccie5f11682019-03-22 07:21:49 +0000870 ConstBytes blob) {
871 protos::pbzero::SysEnterFtraceEvent::Decoder evt(blob.data, blob.size);
872 uint32_t syscall_num = static_cast<uint32_t>(evt.id());
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100873 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
Hector Dearmanf31a7032019-03-29 10:05:09 +0000874
Hector Dearmanbd6cd472019-02-13 16:42:52 +0000875 if (is_enter) {
Hector Dearmanf31a7032019-03-29 10:05:09 +0000876 context_->syscall_tracker->Enter(ts, utid, syscall_num);
Hector Dearmanbd6cd472019-02-13 16:42:52 +0000877 } else {
Hector Dearmanf31a7032019-03-29 10:05:09 +0000878 context_->syscall_tracker->Exit(ts, utid, syscall_num);
Hector Dearmanbd6cd472019-02-13 16:42:52 +0000879 }
880
881 // We are reusing the same function for sys_enter and sys_exit.
882 // It is fine as the arguments are the same, but we need to be sure that the
883 // protobuf field id for both are the same.
Primiano Tuccie5f11682019-03-22 07:21:49 +0000884 static_assert(
885 static_cast<int>(protos::pbzero::SysEnterFtraceEvent::kIdFieldNumber) ==
886 static_cast<int>(protos::pbzero::SysExitFtraceEvent::kIdFieldNumber),
887 "field mismatch");
Hector Dearmanbd6cd472019-02-13 16:42:52 +0000888}
889
Primiano Tuccie5f11682019-03-22 07:21:49 +0000890void ProtoTraceParser::ParseGenericFtrace(int64_t ts,
Lalit Magantie87cc812019-01-10 15:20:06 +0000891 uint32_t cpu,
Lalit Maganti1d915a62019-01-07 12:10:42 +0000892 uint32_t tid,
Primiano Tuccie5f11682019-03-22 07:21:49 +0000893 ConstBytes blob) {
894 protos::pbzero::GenericFtraceEvent::Decoder evt(blob.data, blob.size);
895 StringId event_id = context_->storage->InternString(evt.event_name());
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100896 UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
Lalit Maganti1d915a62019-01-07 12:10:42 +0000897 RowId row_id = context_->storage->mutable_raw_events()->AddRawEvent(
Primiano Tuccie5f11682019-03-22 07:21:49 +0000898 ts, event_id, cpu, utid);
Lalit Maganti1d915a62019-01-07 12:10:42 +0000899
Primiano Tuccie5f11682019-03-22 07:21:49 +0000900 for (auto it = evt.field(); it; ++it) {
901 protos::pbzero::GenericFtraceEvent::Field::Decoder fld(it->data(),
902 it->size());
903 auto field_name_id = context_->storage->InternString(fld.name());
904 if (fld.has_int_value()) {
905 context_->args_tracker->AddArg(row_id, field_name_id, field_name_id,
906 Variadic::Integer(fld.int_value()));
907 } else if (fld.has_uint_value()) {
908 context_->args_tracker->AddArg(
909 row_id, field_name_id, field_name_id,
910 Variadic::Integer(static_cast<int64_t>(fld.uint_value())));
911 } else if (fld.has_str_value()) {
912 StringId str_value = context_->storage->InternString(fld.str_value());
913 context_->args_tracker->AddArg(row_id, field_name_id, field_name_id,
914 Variadic::String(str_value));
Lalit Maganti1d915a62019-01-07 12:10:42 +0000915 }
916 }
917}
918
919void ProtoTraceParser::ParseTypedFtraceToRaw(uint32_t ftrace_id,
Primiano Tuccie5f11682019-03-22 07:21:49 +0000920 int64_t ts,
Lalit Magantie87cc812019-01-10 15:20:06 +0000921 uint32_t cpu,
Lalit Maganti1d915a62019-01-07 12:10:42 +0000922 uint32_t tid,
Primiano Tuccie5f11682019-03-22 07:21:49 +0000923 ConstBytes blob) {
924 ProtoDecoder decoder(blob.data, blob.size);
Lalit Maganti1d915a62019-01-07 12:10:42 +0000925 if (ftrace_id >= GetDescriptorsSize()) {
926 PERFETTO_DLOG("Event with id: %d does not exist and cannot be parsed.",
927 ftrace_id);
928 return;
929 }
Lalit Magantid86161a2019-02-06 15:07:13 +0000930
Lalit Maganti1d915a62019-01-07 12:10:42 +0000931 MessageDescriptor* m = GetMessageDescriptorForId(ftrace_id);
Lalit Magantid86161a2019-02-06 15:07:13 +0000932 const auto& message_strings = ftrace_message_strings_[ftrace_id];
Ioannis Ilkosb5fa2602019-04-17 16:56:01 +0100933 UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
Lalit Maganti1d915a62019-01-07 12:10:42 +0000934 RowId raw_event_id = context_->storage->mutable_raw_events()->AddRawEvent(
Primiano Tuccie5f11682019-03-22 07:21:49 +0000935 ts, message_strings.message_name_id, cpu, utid);
Primiano Tuccic1678872019-03-20 11:30:54 +0000936 for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
937 if (PERFETTO_UNLIKELY(fld.id() >= kMaxFtraceEventFields)) {
Ryan Savitski717d5542019-03-18 12:00:16 +0000938 PERFETTO_DLOG(
Primiano Tuccic1678872019-03-20 11:30:54 +0000939 "Skipping ftrace arg - proto field id is too large (%" PRIu16 ")",
940 fld.id());
Ryan Savitski717d5542019-03-18 12:00:16 +0000941 continue;
942 }
Primiano Tuccic1678872019-03-20 11:30:54 +0000943 ProtoSchemaType type = m->fields[fld.id()].type;
944 StringId name_id = message_strings.field_name_ids[fld.id()];
Lalit Maganti1d915a62019-01-07 12:10:42 +0000945 switch (type) {
946 case ProtoSchemaType::kUint32:
947 case ProtoSchemaType::kInt32:
948 case ProtoSchemaType::kUint64:
949 case ProtoSchemaType::kInt64:
950 case ProtoSchemaType::kFixed64:
951 case ProtoSchemaType::kFixed32:
952 case ProtoSchemaType::kSfixed32:
953 case ProtoSchemaType::kSfixed64:
954 case ProtoSchemaType::kSint32:
955 case ProtoSchemaType::kSint64:
956 case ProtoSchemaType::kBool:
957 case ProtoSchemaType::kEnum: {
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +0000958 context_->args_tracker->AddArg(raw_event_id, name_id, name_id,
Primiano Tuccic1678872019-03-20 11:30:54 +0000959 Variadic::Integer(fld.as_int64()));
Lalit Maganti1d915a62019-01-07 12:10:42 +0000960 break;
961 }
962 case ProtoSchemaType::kString:
963 case ProtoSchemaType::kBytes: {
964 StringId value = context_->storage->InternString(fld.as_string());
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +0000965 context_->args_tracker->AddArg(raw_event_id, name_id, name_id,
966 Variadic::String(value));
Lalit Maganti1d915a62019-01-07 12:10:42 +0000967 break;
968 }
Primiano Tuccic1678872019-03-20 11:30:54 +0000969 case ProtoSchemaType::kDouble: {
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +0000970 context_->args_tracker->AddArg(raw_event_id, name_id, name_id,
Primiano Tuccic1678872019-03-20 11:30:54 +0000971 Variadic::Real(fld.as_double()));
972 break;
973 }
974 case ProtoSchemaType::kFloat: {
975 context_->args_tracker->AddArg(
976 raw_event_id, name_id, name_id,
977 Variadic::Real(static_cast<double>(fld.as_float())));
Lalit Maganti1d915a62019-01-07 12:10:42 +0000978 break;
979 }
980 case ProtoSchemaType::kUnknown:
981 case ProtoSchemaType::kGroup:
982 case ProtoSchemaType::kMessage:
983 PERFETTO_DLOG("Could not store %s as a field in args table.",
984 ProtoSchemaToString(type));
985 break;
986 }
987 }
988}
989
Primiano Tuccie5f11682019-03-22 07:21:49 +0000990void ProtoTraceParser::ParseClockSnapshot(ConstBytes blob) {
991 protos::pbzero::ClockSnapshot::Decoder evt(blob.data, blob.size);
Primiano Tuccia270f012019-01-07 20:01:00 +0000992 int64_t clock_boottime = 0;
993 int64_t clock_monotonic = 0;
994 int64_t clock_realtime = 0;
Primiano Tuccie5f11682019-03-22 07:21:49 +0000995 for (auto it = evt.clocks(); it; ++it) {
996 protos::pbzero::ClockSnapshot::Clock::Decoder clk(it->data(), it->size());
997 if (clk.type() == protos::pbzero::ClockSnapshot::Clock::BOOTTIME) {
998 clock_boottime = static_cast<int64_t>(clk.timestamp());
999 } else if (clk.type() == protos::pbzero::ClockSnapshot::Clock::REALTIME) {
1000 clock_realtime = static_cast<int64_t>(clk.timestamp());
1001 } else if (clk.type() == protos::pbzero::ClockSnapshot::Clock::MONOTONIC) {
1002 clock_monotonic = static_cast<int64_t>(clk.timestamp());
Primiano Tuccia270f012019-01-07 20:01:00 +00001003 }
1004 }
Primiano Tuccia270f012019-01-07 20:01:00 +00001005
1006 // Usually these snapshots come all together.
1007 PERFETTO_DCHECK(clock_boottime > 0 && clock_monotonic > 0 &&
1008 clock_realtime > 0);
1009
1010 if (clock_boottime <= 0) {
1011 PERFETTO_ELOG("ClockSnapshot has an invalid BOOTTIME (%" PRId64 ")",
1012 clock_boottime);
Primiano Tucci0e38a142019-01-07 20:51:09 +00001013 context_->storage->IncrementStats(stats::invalid_clock_snapshots);
Primiano Tuccia270f012019-01-07 20:01:00 +00001014 return;
1015 }
1016
1017 auto* ct = context_->clock_tracker.get();
1018
1019 // |clock_boottime| is used as the reference trace time.
1020 ct->SyncClocks(ClockDomain::kBootTime, clock_boottime, clock_boottime);
1021
1022 if (clock_monotonic > 0)
1023 ct->SyncClocks(ClockDomain::kMonotonic, clock_monotonic, clock_boottime);
1024
1025 if (clock_realtime > 0)
1026 ct->SyncClocks(ClockDomain::kRealTime, clock_realtime, clock_boottime);
1027}
1028
Primiano Tuccie5f11682019-03-22 07:21:49 +00001029void ProtoTraceParser::ParseAndroidLogPacket(ConstBytes blob) {
1030 protos::pbzero::AndroidLogPacket::Decoder packet(blob.data, blob.size);
1031 for (auto it = packet.events(); it; ++it)
1032 ParseAndroidLogEvent(it->as_bytes());
Primiano Tuccia270f012019-01-07 20:01:00 +00001033
Primiano Tuccie5f11682019-03-22 07:21:49 +00001034 if (packet.has_stats())
1035 ParseAndroidLogStats(packet.stats());
Primiano Tuccia270f012019-01-07 20:01:00 +00001036}
1037
Primiano Tuccie5f11682019-03-22 07:21:49 +00001038void ProtoTraceParser::ParseAndroidLogEvent(ConstBytes blob) {
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001039 // TODO(primiano): Add events and non-stringified fields to the "raw" table.
Primiano Tuccie5f11682019-03-22 07:21:49 +00001040 protos::pbzero::AndroidLogPacket::LogEvent::Decoder evt(blob.data, blob.size);
1041 int64_t ts = static_cast<int64_t>(evt.timestamp());
1042 uint32_t pid = static_cast<uint32_t>(evt.pid());
1043 uint32_t tid = static_cast<uint32_t>(evt.tid());
1044 uint8_t prio = static_cast<uint8_t>(evt.prio());
Lalit Magantid63ec5a2019-03-28 13:55:56 +00001045 StringId tag_id = context_->storage->InternString(
1046 evt.has_tag() ? evt.tag() : base::StringView());
1047 StringId msg_id = context_->storage->InternString(
1048 evt.has_message() ? evt.message() : base::StringView());
Primiano Tuccie5f11682019-03-22 07:21:49 +00001049
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001050 char arg_msg[4096];
1051 char* arg_str = &arg_msg[0];
1052 *arg_str = '\0';
1053 auto arg_avail = [&arg_msg, &arg_str]() {
1054 return sizeof(arg_msg) - static_cast<size_t>(arg_str - arg_msg);
1055 };
Primiano Tuccie5f11682019-03-22 07:21:49 +00001056 for (auto it = evt.args(); it; ++it) {
1057 protos::pbzero::AndroidLogPacket::LogEvent::Arg::Decoder arg(it->data(),
1058 it->size());
1059 if (!arg.has_name())
1060 continue;
1061 arg_str +=
1062 snprintf(arg_str, arg_avail(),
1063 " %.*s=", static_cast<int>(arg.name().size), arg.name().data);
1064 if (arg.has_string_value()) {
1065 arg_str += snprintf(arg_str, arg_avail(), "\"%.*s\"",
1066 static_cast<int>(arg.string_value().size),
1067 arg.string_value().data);
1068 } else if (arg.has_int_value()) {
1069 arg_str += snprintf(arg_str, arg_avail(), "%" PRId64, arg.int_value());
1070 } else if (arg.has_float_value()) {
1071 arg_str += snprintf(arg_str, arg_avail(), "%f",
1072 static_cast<double>(arg.float_value()));
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001073 }
1074 }
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001075
1076 if (prio == 0)
Primiano Tuccie5f11682019-03-22 07:21:49 +00001077 prio = protos::pbzero::AndroidLogPriority::PRIO_INFO;
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001078
1079 if (arg_str != &arg_msg[0]) {
1080 PERFETTO_DCHECK(!msg_id);
1081 // Skip the first space char (" foo=1 bar=2" -> "foo=1 bar=2").
1082 msg_id = context_->storage->InternString(&arg_msg[1]);
1083 }
1084 UniquePid utid = tid ? context_->process_tracker->UpdateThread(tid, pid) : 0;
Hector Dearmanba43f602019-01-29 14:36:11 +00001085 base::Optional<int64_t> opt_trace_time =
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001086 context_->clock_tracker->ToTraceTime(ClockDomain::kRealTime, ts);
Hector Dearmanba43f602019-01-29 14:36:11 +00001087 if (!opt_trace_time)
1088 return;
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001089
1090 // Log events are NOT required to be sorted by trace_time. The virtual table
1091 // will take care of sorting on-demand.
Hector Dearmanba43f602019-01-29 14:36:11 +00001092 context_->storage->mutable_android_log()->AddLogEvent(
1093 opt_trace_time.value(), utid, prio, tag_id, msg_id);
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001094}
1095
Primiano Tuccie5f11682019-03-22 07:21:49 +00001096void ProtoTraceParser::ParseAndroidLogStats(ConstBytes blob) {
1097 protos::pbzero::AndroidLogPacket::Stats::Decoder evt(blob.data, blob.size);
1098 if (evt.has_num_failed()) {
1099 context_->storage->SetStats(stats::android_log_num_failed,
1100 static_cast<int64_t>(evt.num_failed()));
1101 }
1102
1103 if (evt.has_num_skipped()) {
1104 context_->storage->SetStats(stats::android_log_num_skipped,
1105 static_cast<int64_t>(evt.num_skipped()));
1106 }
1107
1108 if (evt.has_num_total()) {
1109 context_->storage->SetStats(stats::android_log_num_total,
1110 static_cast<int64_t>(evt.num_total()));
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001111 }
1112}
1113
Primiano Tuccie5f11682019-03-22 07:21:49 +00001114void ProtoTraceParser::ParseTraceStats(ConstBytes blob) {
1115 protos::pbzero::TraceStats::Decoder evt(blob.data, blob.size);
1116 auto* storage = context_->storage.get();
1117 storage->SetStats(stats::traced_producers_connected,
1118 static_cast<int64_t>(evt.producers_connected()));
1119 storage->SetStats(stats::traced_data_sources_registered,
1120 static_cast<int64_t>(evt.data_sources_registered()));
1121 storage->SetStats(stats::traced_data_sources_seen,
1122 static_cast<int64_t>(evt.data_sources_seen()));
1123 storage->SetStats(stats::traced_tracing_sessions,
1124 static_cast<int64_t>(evt.tracing_sessions()));
1125 storage->SetStats(stats::traced_total_buffers,
1126 static_cast<int64_t>(evt.total_buffers()));
1127 storage->SetStats(stats::traced_chunks_discarded,
1128 static_cast<int64_t>(evt.chunks_discarded()));
1129 storage->SetStats(stats::traced_patches_discarded,
1130 static_cast<int64_t>(evt.patches_discarded()));
Primiano Tucci0e38a142019-01-07 20:51:09 +00001131
Primiano Tucci0e38a142019-01-07 20:51:09 +00001132 int buf_num = 0;
Primiano Tuccie5f11682019-03-22 07:21:49 +00001133 for (auto it = evt.buffer_stats(); it; ++it, ++buf_num) {
1134 protos::pbzero::TraceStats::BufferStats::Decoder buf(it->data(),
1135 it->size());
1136 storage->SetIndexedStats(stats::traced_buf_buffer_size, buf_num,
1137 static_cast<int64_t>(buf.buffer_size()));
1138 storage->SetIndexedStats(stats::traced_buf_bytes_written, buf_num,
1139 static_cast<int64_t>(buf.bytes_written()));
1140 storage->SetIndexedStats(stats::traced_buf_bytes_overwritten, buf_num,
1141 static_cast<int64_t>(buf.bytes_overwritten()));
1142 storage->SetIndexedStats(stats::traced_buf_bytes_read, buf_num,
1143 static_cast<int64_t>(buf.bytes_read()));
1144 storage->SetIndexedStats(stats::traced_buf_padding_bytes_written, buf_num,
1145 static_cast<int64_t>(buf.padding_bytes_written()));
1146 storage->SetIndexedStats(stats::traced_buf_padding_bytes_cleared, buf_num,
1147 static_cast<int64_t>(buf.padding_bytes_cleared()));
1148 storage->SetIndexedStats(stats::traced_buf_chunks_written, buf_num,
1149 static_cast<int64_t>(buf.chunks_written()));
1150 storage->SetIndexedStats(stats::traced_buf_chunks_rewritten, buf_num,
1151 static_cast<int64_t>(buf.chunks_rewritten()));
1152 storage->SetIndexedStats(stats::traced_buf_chunks_overwritten, buf_num,
1153 static_cast<int64_t>(buf.chunks_overwritten()));
1154 storage->SetIndexedStats(stats::traced_buf_chunks_discarded, buf_num,
1155 static_cast<int64_t>(buf.chunks_discarded()));
1156 storage->SetIndexedStats(stats::traced_buf_chunks_read, buf_num,
1157 static_cast<int64_t>(buf.chunks_read()));
1158 storage->SetIndexedStats(
1159 stats::traced_buf_chunks_committed_out_of_order, buf_num,
1160 static_cast<int64_t>(buf.chunks_committed_out_of_order()));
1161 storage->SetIndexedStats(stats::traced_buf_write_wrap_count, buf_num,
1162 static_cast<int64_t>(buf.write_wrap_count()));
1163 storage->SetIndexedStats(stats::traced_buf_patches_succeeded, buf_num,
1164 static_cast<int64_t>(buf.patches_succeeded()));
1165 storage->SetIndexedStats(stats::traced_buf_patches_failed, buf_num,
1166 static_cast<int64_t>(buf.patches_failed()));
1167 storage->SetIndexedStats(stats::traced_buf_readaheads_succeeded, buf_num,
1168 static_cast<int64_t>(buf.readaheads_succeeded()));
1169 storage->SetIndexedStats(stats::traced_buf_readaheads_failed, buf_num,
1170 static_cast<int64_t>(buf.readaheads_failed()));
Primiano Tucci0e38a142019-01-07 20:51:09 +00001171 }
Primiano Tucci0e38a142019-01-07 20:51:09 +00001172}
1173
Primiano Tuccie5f11682019-03-22 07:21:49 +00001174void ProtoTraceParser::ParseFtraceStats(ConstBytes blob) {
1175 protos::pbzero::FtraceStats::Decoder evt(blob.data, blob.size);
1176 size_t phase =
1177 evt.phase() == protos::pbzero::FtraceStats_Phase_END_OF_TRACE ? 1 : 0;
Primiano Tucci0e38a142019-01-07 20:51:09 +00001178
Primiano Tuccie5f11682019-03-22 07:21:49 +00001179 // This code relies on the fact that each ftrace_cpu_XXX_end event is
1180 // just after the corresponding ftrace_cpu_XXX_begin event.
1181 static_assert(
1182 stats::ftrace_cpu_read_events_end - stats::ftrace_cpu_read_events_begin ==
1183 1 &&
1184 stats::ftrace_cpu_entries_end - stats::ftrace_cpu_entries_begin == 1,
1185 "ftrace_cpu_XXX stats definition are messed up");
1186
1187 auto* storage = context_->storage.get();
1188 for (auto it = evt.cpu_stats(); it; ++it) {
1189 protos::pbzero::FtraceCpuStats::Decoder cpu_stats(it->data(), it->size());
1190 int cpu = static_cast<int>(cpu_stats.cpu());
1191 storage->SetIndexedStats(stats::ftrace_cpu_entries_begin + phase, cpu,
1192 static_cast<int64_t>(cpu_stats.entries()));
1193 storage->SetIndexedStats(stats::ftrace_cpu_overrun_begin + phase, cpu,
1194 static_cast<int64_t>(cpu_stats.overrun()));
1195 storage->SetIndexedStats(stats::ftrace_cpu_commit_overrun_begin + phase,
1196 cpu,
1197 static_cast<int64_t>(cpu_stats.commit_overrun()));
1198 storage->SetIndexedStats(stats::ftrace_cpu_bytes_read_begin + phase, cpu,
1199 static_cast<int64_t>(cpu_stats.bytes_read()));
Lalit Maganti08ca56e2019-04-03 11:04:51 +01001200
1201 // oldest_event_ts can often be set to very high values, possibly because
1202 // of wrapping. Ensure that we are not overflowing to avoid ubsan
1203 // complaining.
1204 double oldest_event_ts = cpu_stats.oldest_event_ts() * 1e9;
1205 if (oldest_event_ts >= std::numeric_limits<int64_t>::max()) {
1206 storage->SetIndexedStats(stats::ftrace_cpu_oldest_event_ts_begin + phase,
1207 cpu, std::numeric_limits<int64_t>::max());
1208 } else {
1209 storage->SetIndexedStats(stats::ftrace_cpu_oldest_event_ts_begin + phase,
1210 cpu, static_cast<int64_t>(oldest_event_ts));
1211 }
1212
Primiano Tuccie5f11682019-03-22 07:21:49 +00001213 storage->SetIndexedStats(stats::ftrace_cpu_now_ts_begin + phase, cpu,
1214 static_cast<int64_t>(cpu_stats.now_ts() * 1e9));
1215 storage->SetIndexedStats(stats::ftrace_cpu_dropped_events_begin + phase,
1216 cpu,
1217 static_cast<int64_t>(cpu_stats.dropped_events()));
1218 storage->SetIndexedStats(stats::ftrace_cpu_read_events_begin + phase, cpu,
1219 static_cast<int64_t>(cpu_stats.read_events()));
Primiano Tucci0e38a142019-01-07 20:51:09 +00001220 }
Primiano Tucci0e38a142019-01-07 20:51:09 +00001221}
1222
Florian Mayer12c89992019-05-14 13:03:10 +01001223void ProtoTraceParser::ParseProfilePacket(int64_t ts, ConstBytes blob) {
1224 static uint64_t index = 0;
Primiano Tuccie5f11682019-03-22 07:21:49 +00001225 protos::pbzero::ProfilePacket::Decoder packet(blob.data, blob.size);
Florian Mayer438b5ab2019-05-02 11:18:06 +01001226
Primiano Tuccie5f11682019-03-22 07:21:49 +00001227 for (auto it = packet.strings(); it; ++it) {
1228 protos::pbzero::ProfilePacket::InternedString::Decoder entry(it->data(),
1229 it->size());
1230
1231 const char* str = reinterpret_cast<const char*>(entry.str().data);
Florian Mayer438b5ab2019-05-02 11:18:06 +01001232 auto str_id = context_->storage->InternString(
1233 base::StringView(str, entry.str().size));
1234 context_->heap_profile_tracker->AddString(index, entry.id(), str_id);
Hector Dearmandd639792019-01-31 15:04:59 +00001235 }
Florian Mayer438b5ab2019-05-02 11:18:06 +01001236
1237 for (auto it = packet.mappings(); it; ++it) {
1238 protos::pbzero::ProfilePacket::Mapping::Decoder entry(it->data(),
1239 it->size());
1240 HeapProfileTracker::SourceMapping src_mapping;
1241 src_mapping.build_id = entry.build_id();
1242 src_mapping.offset = entry.offset();
1243 src_mapping.start = entry.start();
1244 src_mapping.end = entry.end();
1245 src_mapping.load_bias = entry.load_bias();
1246 src_mapping.name_id = 0;
1247 for (auto path_string_id_it = entry.path_string_ids(); path_string_id_it;
1248 ++path_string_id_it)
1249 src_mapping.name_id = path_string_id_it->as_uint64();
1250 context_->heap_profile_tracker->AddMapping(index, entry.id(), src_mapping);
1251 }
1252
1253 for (auto it = packet.frames(); it; ++it) {
1254 protos::pbzero::ProfilePacket::Frame::Decoder entry(it->data(), it->size());
1255 HeapProfileTracker::SourceFrame src_frame;
1256 src_frame.name_id = entry.function_name_id();
1257 src_frame.mapping_id = entry.mapping_id();
1258 src_frame.rel_pc = entry.rel_pc();
1259
1260 context_->heap_profile_tracker->AddFrame(index, entry.id(), src_frame);
1261 }
1262
1263 for (auto it = packet.callstacks(); it; ++it) {
1264 protos::pbzero::ProfilePacket::Callstack::Decoder entry(it->data(),
1265 it->size());
1266 HeapProfileTracker::SourceCallstack src_callstack;
1267 for (auto frame_it = entry.frame_ids(); frame_it; ++frame_it)
1268 src_callstack.emplace_back(frame_it->as_uint64());
1269
1270 context_->heap_profile_tracker->AddCallstack(index, entry.id(),
1271 src_callstack);
1272 }
1273
1274 for (auto it = packet.process_dumps(); it; ++it) {
1275 protos::pbzero::ProfilePacket::ProcessHeapSamples::Decoder entry(
1276 it->data(), it->size());
1277
1278 int pid = static_cast<int>(entry.pid());
1279
1280 if (entry.buffer_corrupted())
1281 context_->storage->IncrementIndexedStats(
1282 stats::heapprofd_buffer_corrupted, pid);
1283 if (entry.buffer_overran())
1284 context_->storage->IncrementIndexedStats(stats::heapprofd_buffer_overran,
1285 pid);
1286 if (entry.rejected_concurrent())
1287 context_->storage->IncrementIndexedStats(
1288 stats::heapprofd_rejected_concurrent, pid);
1289
1290 for (auto sample_it = entry.samples(); sample_it; ++sample_it) {
1291 protos::pbzero::ProfilePacket::HeapSample::Decoder sample(
1292 sample_it->data(), sample_it->size());
1293
1294 HeapProfileTracker::SourceAllocation src_allocation;
1295 src_allocation.pid = entry.pid();
Florian Mayer12c89992019-05-14 13:03:10 +01001296 src_allocation.timestamp = ts;
Florian Mayer438b5ab2019-05-02 11:18:06 +01001297 src_allocation.callstack_id = sample.callstack_id();
1298 src_allocation.self_allocated = sample.self_allocated();
1299 src_allocation.self_freed = sample.self_freed();
1300 src_allocation.alloc_count = sample.alloc_count();
1301 src_allocation.free_count = sample.free_count();
1302
1303 context_->heap_profile_tracker->StoreAllocation(index, src_allocation);
1304 }
1305 }
Florian Mayerbee52132019-05-02 13:59:56 +01001306 if (!packet.continued()) {
1307 context_->heap_profile_tracker->ApplyAllAllocations();
Florian Mayer438b5ab2019-05-02 11:18:06 +01001308 index++;
Florian Mayerbee52132019-05-02 13:59:56 +01001309 }
Hector Dearmandd639792019-01-31 15:04:59 +00001310}
1311
Hector Dearmanf31a7032019-03-29 10:05:09 +00001312void ProtoTraceParser::ParseSystemInfo(ConstBytes blob) {
1313 protos::pbzero::SystemInfo::Decoder packet(blob.data, blob.size);
1314 if (packet.has_utsname()) {
1315 ConstBytes utsname_blob = packet.utsname();
1316 protos::pbzero::Utsname::Decoder utsname(utsname_blob.data,
1317 utsname_blob.size);
1318 base::StringView machine = utsname.machine();
1319 if (machine == "aarch64" || machine == "armv8l") {
1320 context_->syscall_tracker->SetArchitecture(kAarch64);
1321 } else if (machine == "x86_64") {
1322 context_->syscall_tracker->SetArchitecture(kX86_64);
1323 } else {
1324 PERFETTO_ELOG("Unknown architecture %s", machine.ToStdString().c_str());
1325 }
1326 }
1327}
1328
Eric Seckler56a007d2019-05-02 16:25:14 +01001329void ProtoTraceParser::ParseTrackEvent(
1330 int64_t ts,
1331 int64_t /*tts*/,
1332 ProtoIncrementalState::PacketSequenceState* sequence_state,
1333 ConstBytes blob) {
1334 protos::pbzero::TrackEvent::Decoder event(blob.data, blob.size);
1335
1336 const auto legacy_event_blob = event.legacy_event();
1337 protos::pbzero::TrackEvent::LegacyEvent::Decoder legacy_event(
1338 legacy_event_blob.data, legacy_event_blob.size);
1339
1340 // TODO(eseckler): This legacy event field will eventually be replaced by
1341 // fields in TrackEvent itself.
1342 if (PERFETTO_UNLIKELY(!legacy_event.has_phase())) {
1343 PERFETTO_ELOG("TrackEvent without phase");
1344 return;
1345 }
1346
1347 ProcessTracker* procs = context_->process_tracker.get();
1348 TraceStorage* storage = context_->storage.get();
1349 SliceTracker* slice_tracker = context_->slice_tracker.get();
1350
1351 uint32_t pid = static_cast<uint32_t>(sequence_state->pid());
1352 uint32_t tid = static_cast<uint32_t>(sequence_state->tid());
1353 if (legacy_event.has_pid_override())
1354 pid = static_cast<uint32_t>(legacy_event.pid_override());
1355 if (legacy_event.has_tid_override())
1356 tid = static_cast<uint32_t>(legacy_event.tid_override());
1357 UniqueTid utid = procs->UpdateThread(tid, pid);
1358
1359 std::vector<uint32_t> category_iids;
1360 for (auto it = event.category_iids(); it; ++it) {
1361 category_iids.push_back(it->as_uint32());
1362 }
1363
1364 StringId category_id = 0;
1365
1366 // If there's a single category, we can avoid building a concatenated string.
1367 if (PERFETTO_LIKELY(category_iids.size() == 1)) {
1368 auto* map =
1369 sequence_state->GetInternedDataMap<protos::pbzero::EventCategory>();
1370 auto cat_view_it = map->find(category_iids[0]);
1371 if (cat_view_it == map->end()) {
1372 PERFETTO_ELOG("Could not find category interning entry for ID %u",
1373 category_iids[0]);
1374 } else {
1375 // If the name is already in the pool, no need to decode it again.
1376 if (cat_view_it->second.storage_refs) {
1377 category_id = cat_view_it->second.storage_refs->name_id;
1378 } else {
1379 auto cat = cat_view_it->second.CreateDecoder();
1380 category_id = storage->InternString(cat.name());
1381 // Avoid having to decode & look up the name again in the future.
1382 cat_view_it->second.storage_refs =
1383 ProtoIncrementalState::StorageReferences<
1384 protos::pbzero::EventCategory>{category_id};
1385 }
1386 }
1387 } else if (category_iids.size() > 1) {
1388 auto* map =
1389 sequence_state->GetInternedDataMap<protos::pbzero::EventCategory>();
1390 // We concatenate the category strings together since we currently only
1391 // support a single "cat" column.
1392 // TODO(eseckler): Support multi-category events in the table schema.
1393 std::string categories;
1394 for (uint32_t iid : category_iids) {
1395 auto cat_view_it = map->find(iid);
1396 if (cat_view_it == map->end()) {
1397 PERFETTO_ELOG("Could not find category interning entry for ID %u", iid);
1398 continue;
1399 }
1400 auto cat = cat_view_it->second.CreateDecoder();
1401 base::StringView name = cat.name();
1402 if (!categories.empty())
1403 categories.append(",");
1404 categories.append(name.data(), name.size());
1405 }
1406 if (!categories.empty())
1407 category_id = storage->InternString(base::StringView(categories));
1408 } else {
1409 PERFETTO_ELOG("TrackEvent without category");
1410 }
1411
1412 StringId name_id = 0;
1413
1414 if (PERFETTO_LIKELY(legacy_event.name_iid())) {
1415 auto* map =
1416 sequence_state->GetInternedDataMap<protos::pbzero::LegacyEventName>();
1417 auto name_view_it = map->find(legacy_event.name_iid());
1418 if (name_view_it == map->end()) {
1419 PERFETTO_ELOG("Could not find event name interning entry for ID %u",
1420 legacy_event.name_iid());
1421 } else {
1422 // If the name is already in the pool, no need to decode it again.
1423 if (name_view_it->second.storage_refs) {
1424 name_id = name_view_it->second.storage_refs->name_id;
1425 } else {
1426 auto event_name = name_view_it->second.CreateDecoder();
1427 name_id = storage->InternString(event_name.name());
1428 // Avoid having to decode & look up the name again in the future.
1429 name_view_it->second.storage_refs =
1430 ProtoIncrementalState::StorageReferences<
1431 protos::pbzero::LegacyEventName>{name_id};
1432 }
1433 }
1434 }
1435
1436 // TODO(eseckler): Handle thread timestamp/duration, debug annotations, task
1437 // souce locations, legacy event attributes, ...
1438
1439 int32_t phase = legacy_event.phase();
1440 switch (static_cast<char>(phase)) {
1441 case 'B': { // TRACE_EVENT_PHASE_BEGIN.
1442 slice_tracker->Begin(ts, utid, category_id, name_id);
1443 break;
1444 }
1445 case 'E': { // TRACE_EVENT_PHASE_END.
1446 slice_tracker->End(ts, utid, category_id, name_id);
1447 break;
1448 }
1449 case 'X': { // TRACE_EVENT_PHASE_COMPLETE.
1450 auto duration_ns = legacy_event.duration_us() * 1000;
1451 if (duration_ns < 0)
1452 return;
1453 slice_tracker->Scoped(ts, utid, category_id, name_id, duration_ns);
1454 break;
1455 }
1456 case 'M': { // TRACE_EVENT_PHASE_METADATA (process and thread names).
1457 // For now, we just compare the event name and assume there's a single
1458 // argument in these events with the name of the process/thread.
1459 // TODO(eseckler): Use names from process/thread descriptors instead.
1460 NullTermStringView event_name = storage->GetString(name_id);
1461 PERFETTO_DCHECK(event_name.data());
1462 if (strcmp(event_name.c_str(), "thread_name") == 0) {
1463 auto it = event.debug_annotations();
1464 if (!it)
1465 break;
1466 protos::pbzero::DebugAnnotation::Decoder annotation(it->data(),
1467 it->size());
1468 auto thread_name = annotation.string_value();
1469 if (!thread_name.size)
1470 break;
1471 auto thread_name_id = context_->storage->InternString(thread_name);
1472 procs->UpdateThreadName(tid, thread_name_id);
1473 } else if (strcmp(event_name.c_str(), "process_name") == 0) {
1474 auto it = event.debug_annotations();
1475 if (!it)
1476 break;
1477 protos::pbzero::DebugAnnotation::Decoder annotation(it->data(),
1478 it->size());
1479 auto process_name = annotation.string_value();
1480 if (!process_name.size)
1481 break;
1482 procs->UpdateProcess(pid, base::nullopt, process_name);
1483 }
1484 break;
1485 }
1486 }
1487}
1488
Mikhail Khokhlovb1fe42a2019-05-23 13:58:05 +01001489void ProtoTraceParser::ParseChromeBenchmarkMetadata(ConstBytes blob) {
1490 TraceStorage* storage = context_->storage.get();
1491 protos::pbzero::ChromeBenchmarkMetadata::Decoder packet(blob.data, blob.size);
1492 if (packet.has_benchmark_name()) {
1493 auto benchmark_name_id = storage->InternString(packet.benchmark_name());
1494 storage->SetMetadata(metadata::benchmark_name,
1495 Variadic::String(benchmark_name_id));
1496 }
1497 if (packet.has_benchmark_description()) {
1498 auto benchmark_description_id =
1499 storage->InternString(packet.benchmark_description());
1500 storage->SetMetadata(metadata::benchmark_description,
1501 Variadic::String(benchmark_description_id));
1502 }
1503 if (packet.has_label()) {
1504 auto label_id = storage->InternString(packet.label());
1505 storage->SetMetadata(metadata::benchmark_label, Variadic::String(label_id));
1506 }
1507 if (packet.has_story_name()) {
1508 auto story_name_id = storage->InternString(packet.story_name());
1509 storage->SetMetadata(metadata::benchmark_story_name,
1510 Variadic::String(story_name_id));
1511 }
1512 for (auto it = packet.story_tags(); it; ++it) {
1513 auto story_tag_id = storage->InternString(it->as_string());
1514 storage->AppendMetadata(metadata::benchmark_story_tags,
1515 Variadic::String(story_tag_id));
1516 }
1517 if (packet.has_benchmark_start_time_us()) {
1518 storage->SetMetadata(metadata::benchmark_start_time_us,
1519 Variadic::Integer(packet.benchmark_start_time_us()));
1520 }
1521 if (packet.has_story_run_time_us()) {
1522 storage->SetMetadata(metadata::benchmark_story_run_time_us,
1523 Variadic::Integer(packet.story_run_time_us()));
1524 }
1525 if (packet.has_story_run_index()) {
1526 storage->SetMetadata(metadata::benchmark_story_run_index,
1527 Variadic::Integer(packet.story_run_index()));
1528 }
1529 if (packet.has_had_failures()) {
1530 storage->SetMetadata(metadata::benchmark_had_failures,
1531 Variadic::Integer(packet.had_failures()));
1532 }
1533}
1534
Lalit Maganti93b76362018-06-01 03:03:58 +01001535} // namespace trace_processor
1536} // namespace perfetto