blob: 6a876bc338c63e93f2667ec882bebdd1907fa17f [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
Primiano Tucci132a34d2018-09-19 19:34:01 +010019#include <string.h>
20
Lalit Magantidf3e9262018-06-04 17:45:00 +010021#include <string>
22
Primiano Tuccid933d912018-09-04 09:15:07 +010023#include "perfetto/base/logging.h"
Hector Dearmanba43f602019-01-29 14:36:11 +000024#include "perfetto/base/optional.h"
Primiano Tucci2da5d2e2018-08-10 14:23:31 +010025#include "perfetto/base/string_view.h"
Lalit Maganti93b76362018-06-01 03:03:58 +010026#include "perfetto/base/utils.h"
Primiano Tucci0d72a312018-08-07 14:42:45 +010027#include "perfetto/protozero/proto_decoder.h"
Isabelle Taylor54ce7052018-10-01 14:00:15 +010028#include "perfetto/traced/sys_stats_counters.h"
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +000029#include "src/trace_processor/args_tracker.h"
Primiano Tuccia270f012019-01-07 20:01:00 +000030#include "src/trace_processor/clock_tracker.h"
Isabelle Taylora97c5f52018-10-23 17:36:12 +010031#include "src/trace_processor/event_tracker.h"
Lalit Maganti1d915a62019-01-07 12:10:42 +000032#include "src/trace_processor/ftrace_descriptors.h"
Primiano Tucci0d72a312018-08-07 14:42:45 +010033#include "src/trace_processor/process_tracker.h"
Hector Dearman947f12a2018-09-11 16:50:36 +010034#include "src/trace_processor/slice_tracker.h"
Primiano Tucci0d72a312018-08-07 14:42:45 +010035#include "src/trace_processor/trace_processor_context.h"
36
Lalit Magantidf3e9262018-06-04 17:45:00 +010037#include "perfetto/trace/trace.pb.h"
38#include "perfetto/trace/trace_packet.pb.h"
Lalit Maganti93b76362018-06-01 03:03:58 +010039
40namespace perfetto {
41namespace trace_processor {
42
Lalit Maganti1d915a62019-01-07 12:10:42 +000043namespace {
44
45using protozero::ProtoDecoder;
46using Variadic = TraceStorage::Args::Variadic;
47
48} // namespace
49
Hector Dearman947f12a2018-09-11 16:50:36 +010050// We have to handle trace_marker events of a few different types:
51// 1. some random text
52// 2. B|1636|pokeUserActivity
53// 3. E|1636
54// 4. C|1636|wq:monitor|0
55bool ParseSystraceTracePoint(base::StringView str, SystraceTracePoint* out) {
56 // THIS char* IS NOT NULL TERMINATED.
57 const char* s = str.data();
58 size_t len = str.size();
59
Ioannis Ilkos21a76182019-01-28 14:05:01 +000060 // If str matches '[BEC]\|[0-9]+[\|\n]' set tgid_length to the length of
Hector Dearman947f12a2018-09-11 16:50:36 +010061 // the number. Otherwise return false.
Lalit Magantide6267f2018-11-08 12:35:34 +000062 if (s[1] != '|' && s[1] != '\n')
Hector Dearman947f12a2018-09-11 16:50:36 +010063 return false;
64 if (s[0] != 'B' && s[0] != 'E' && s[0] != 'C')
65 return false;
Ioannis Ilkos21a76182019-01-28 14:05:01 +000066 size_t tgid_length = 0;
Lalit Magantide6267f2018-11-08 12:35:34 +000067 for (size_t i = 2; i < len; i++) {
Hector Dearman947f12a2018-09-11 16:50:36 +010068 if (s[i] == '|' || s[i] == '\n') {
Ioannis Ilkos21a76182019-01-28 14:05:01 +000069 tgid_length = i - 2;
Hector Dearman947f12a2018-09-11 16:50:36 +010070 break;
71 }
72 if (s[i] < '0' || s[i] > '9')
73 return false;
74 }
75
Ioannis Ilkos21a76182019-01-28 14:05:01 +000076 if (tgid_length == 0) {
77 out->tgid = 0;
Lalit Magantide6267f2018-11-08 12:35:34 +000078 } else {
Ioannis Ilkos21a76182019-01-28 14:05:01 +000079 std::string tgid_str(s + 2, tgid_length);
80 out->tgid = static_cast<uint32_t>(std::stoi(tgid_str.c_str()));
Lalit Magantide6267f2018-11-08 12:35:34 +000081 }
Hector Dearman947f12a2018-09-11 16:50:36 +010082
83 out->phase = s[0];
84 switch (s[0]) {
85 case 'B': {
Ioannis Ilkos21a76182019-01-28 14:05:01 +000086 size_t name_index = 2 + tgid_length + 1;
Ioannis Ilkos843e4c42019-01-23 17:32:55 +000087 out->name = base::StringView(
88 s + name_index, len - name_index - (s[len - 1] == '\n' ? 1 : 0));
Hector Dearman947f12a2018-09-11 16:50:36 +010089 return true;
90 }
Isabelle Taylor31e04402018-09-19 12:13:25 +010091 case 'E': {
Hector Dearman947f12a2018-09-11 16:50:36 +010092 return true;
Isabelle Taylor31e04402018-09-19 12:13:25 +010093 }
94 case 'C': {
Ioannis Ilkos21a76182019-01-28 14:05:01 +000095 size_t name_index = 2 + tgid_length + 1;
Isabelle Taylor31e04402018-09-19 12:13:25 +010096 size_t name_length = 0;
97 for (size_t i = name_index; i < len; i++) {
98 if (s[i] == '|' || s[i] == '\n') {
99 name_length = i - name_index;
100 break;
101 }
102 }
103 out->name = base::StringView(s + name_index, name_length);
Ioannis Ilkos45b361a2019-01-14 16:51:48 +0000104
Isabelle Taylor31e04402018-09-19 12:13:25 +0100105 size_t value_index = name_index + name_length + 1;
Ioannis Ilkos45b361a2019-01-14 16:51:48 +0000106 size_t value_len = len - value_index;
Isabelle Taylor31e04402018-09-19 12:13:25 +0100107 char value_str[32];
Ioannis Ilkos45b361a2019-01-14 16:51:48 +0000108 if (value_len >= sizeof(value_str)) {
109 return false;
110 }
111 memcpy(value_str, s + value_index, value_len);
112 value_str[value_len] = 0;
Isabelle Taylor31e04402018-09-19 12:13:25 +0100113 out->value = std::stod(value_str);
Hector Dearman947f12a2018-09-11 16:50:36 +0100114 return true;
Isabelle Taylor31e04402018-09-19 12:13:25 +0100115 }
Hector Dearman947f12a2018-09-11 16:50:36 +0100116 default:
117 return false;
118 }
119}
120
Primiano Tucci7e330292018-08-24 19:10:52 +0200121ProtoTraceParser::ProtoTraceParser(TraceProcessorContext* context)
Isabelle Taylor15314ea2018-09-19 11:35:19 +0100122 : context_(context),
Lalit Maganti6e9c55e2018-11-29 12:00:39 +0000123 utid_name_id_(context->storage->InternString("utid")),
Lalit Maganti369ea3c2019-03-05 11:09:42 +0000124 sched_wakeup_name_id_(context->storage->InternString("sched_wakeup")),
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100125 cpu_freq_name_id_(context->storage->InternString("cpufreq")),
Hector Dearman7b794cc2018-11-30 14:35:30 +0000126 cpu_idle_name_id_(context->storage->InternString("cpuidle")),
Lalit Maganti66ed7ad2019-01-11 16:47:26 +0000127 comm_name_id_(context->storage->InternString("comm")),
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100128 num_forks_name_id_(context->storage->InternString("num_forks")),
129 num_irq_total_name_id_(context->storage->InternString("num_irq_total")),
130 num_softirq_total_name_id_(
131 context->storage->InternString("num_softirq_total")),
132 num_irq_name_id_(context->storage->InternString("num_irq")),
133 num_softirq_name_id_(context->storage->InternString("num_softirq")),
134 cpu_times_user_ns_id_(
135 context->storage->InternString("cpu.times.user_ns")),
136 cpu_times_user_ice_ns_id_(
137 context->storage->InternString("cpu.times.user_ice_ns")),
138 cpu_times_system_mode_ns_id_(
139 context->storage->InternString("cpu.times.system_mode_ns")),
140 cpu_times_idle_ns_id_(
141 context->storage->InternString("cpu.times.idle_ns")),
142 cpu_times_io_wait_ns_id_(
143 context->storage->InternString("cpu.times.io_wait_ns")),
144 cpu_times_irq_ns_id_(context->storage->InternString("cpu.times.irq_ns")),
145 cpu_times_softirq_ns_id_(
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100146 context->storage->InternString("cpu.times.softirq_ns")),
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000147 signal_deliver_id_(context->storage->InternString("signal_deliver")),
Primiano Tuccib86e9ca2018-12-03 20:20:11 +0100148 signal_generate_id_(context->storage->InternString("signal_generate")),
149 batt_charge_id_(context->storage->InternString("batt.charge_uah")),
150 batt_capacity_id_(context->storage->InternString("batt.capacity_pct")),
151 batt_current_id_(context->storage->InternString("batt.current_ua")),
152 batt_current_avg_id_(
Primiano Tucci44231042018-12-06 21:34:32 +0000153 context->storage->InternString("batt.current.avg_ua")),
Lalit Maganti66ed7ad2019-01-11 16:47:26 +0000154 lmk_id_(context->storage->InternString("mem.lmk")),
Primiano Tucci90cdc852018-12-21 10:29:44 +0100155 oom_score_adj_id_(context->storage->InternString("oom_score_adj")),
156 ion_total_unknown_id_(context->storage->InternString("mem.ion.unknown")),
157 ion_change_unknown_id_(
158 context->storage->InternString("mem.ion_change.unknown")) {
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100159 for (const auto& name : BuildMeminfoCounterNames()) {
160 meminfo_strs_id_.emplace_back(context->storage->InternString(name));
161 }
162 for (const auto& name : BuildVmstatCounterNames()) {
163 vmstat_strs_id_.emplace_back(context->storage->InternString(name));
164 }
Lalit Maganti6820abc2019-01-21 11:12:23 +0000165 rss_members_.emplace_back(context->storage->InternString("mem.rss.file"));
166 rss_members_.emplace_back(context->storage->InternString("mem.rss.anon"));
Lalit Maganti5a95df22019-01-24 13:28:36 +0000167 rss_members_.emplace_back(context->storage->InternString("mem.swap"));
Lalit Maganti6820abc2019-01-21 11:12:23 +0000168 rss_members_.emplace_back(context->storage->InternString("mem.rss.shmem"));
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100169 rss_members_.emplace_back(
Lalit Maganti6820abc2019-01-21 11:12:23 +0000170 context->storage->InternString("mem.rss.unknown")); // Keep this last.
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700171
Lalit Maganti6820abc2019-01-21 11:12:23 +0000172 using ProcessStats = protos::ProcessStats;
Lalit Maganti41c98922019-01-23 19:35:58 +0000173 proc_stats_process_names_[ProcessStats::Process::kVmSizeKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700174 context->storage->InternString("mem.virt");
Lalit Maganti41c98922019-01-23 19:35:58 +0000175 proc_stats_process_names_[ProcessStats::Process::kVmRssKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700176 context->storage->InternString("mem.rss");
Lalit Maganti41c98922019-01-23 19:35:58 +0000177 proc_stats_process_names_[ProcessStats::Process::kRssAnonKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700178 context->storage->InternString("mem.rss.anon");
Lalit Maganti41c98922019-01-23 19:35:58 +0000179 proc_stats_process_names_[ProcessStats::Process::kRssFileKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700180 context->storage->InternString("mem.rss.file");
Lalit Maganti41c98922019-01-23 19:35:58 +0000181 proc_stats_process_names_[ProcessStats::Process::kRssShmemKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700182 context->storage->InternString("mem.rss.shmem");
Lalit Maganti41c98922019-01-23 19:35:58 +0000183 proc_stats_process_names_[ProcessStats::Process::kVmSwapKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700184 context->storage->InternString("mem.swap");
Lalit Maganti41c98922019-01-23 19:35:58 +0000185 proc_stats_process_names_[ProcessStats::Process::kVmLockedKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700186 context->storage->InternString("mem.locked");
Lalit Maganti41c98922019-01-23 19:35:58 +0000187 proc_stats_process_names_[ProcessStats::Process::kVmHwmKbFieldNumber] =
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700188 context->storage->InternString("mem.rss.watermark");
Lalit Maganti41c98922019-01-23 19:35:58 +0000189 proc_stats_process_names_[ProcessStats::Process::kOomScoreAdjFieldNumber] =
190 oom_score_adj_id_;
Lalit Magantia824c332019-01-23 17:55:58 +0000191
Hector Dearmanbd6cd472019-02-13 16:42:52 +0000192 mm_event_counter_names_ = {
193 {MmEventCounterNames(
194 context->storage->InternString("mem.mm.min_flt.count"),
195 context->storage->InternString("mem.mm.min_flt.max_lat"),
196 context->storage->InternString("mem.mm.min_flt.avg_lat")),
197 MmEventCounterNames(
198 context->storage->InternString("mem.mm.maj_flt.count"),
199 context->storage->InternString("mem.mm.maj_flt.max_lat"),
200 context->storage->InternString("mem.mm.maj_flt.avg_lat")),
201 MmEventCounterNames(
202 context->storage->InternString("mem.mm.read_io.count"),
203 context->storage->InternString("mem.mm.read_io.max_lat"),
204 context->storage->InternString("mem.mm.read_io.avg_lat")),
205 MmEventCounterNames(
206 context->storage->InternString("mem.mm.compaction.count"),
207 context->storage->InternString("mem.mm.compaction.max_lat"),
208 context->storage->InternString("mem.mm.compaction.avg_lat")),
209 MmEventCounterNames(
210 context->storage->InternString("mem.mm.reclaim.count"),
211 context->storage->InternString("mem.mm.reclaim.max_lat"),
212 context->storage->InternString("mem.mm.reclaim.avg_lat")),
213 MmEventCounterNames(
214 context->storage->InternString("mem.mm.swp_flt.count"),
215 context->storage->InternString("mem.mm.swp_flt.max_lat"),
216 context->storage->InternString("mem.mm.swp_flt.avg_lat")),
217 MmEventCounterNames(
218 context->storage->InternString("mem.mm.kern_alloc.count"),
219 context->storage->InternString("mem.mm.kern_alloc.max_lat"),
220 context->storage->InternString("mem.mm.kern_alloc.avg_lat"))}};
221
222 // TODO(hjd): Add the missing syscalls + fix on over arch.
223 sys_name_ids_ = {{context->storage->InternString("sys_restart_syscall"),
224 context->storage->InternString("sys_exit"),
225 context->storage->InternString("sys_fork"),
226 context->storage->InternString("sys_read"),
227 context->storage->InternString("sys_write"),
228 context->storage->InternString("sys_open"),
229 context->storage->InternString("sys_close"),
230 context->storage->InternString("sys_creat"),
231 context->storage->InternString("sys_link"),
232 context->storage->InternString("sys_unlink"),
233 context->storage->InternString("sys_execve"),
234 context->storage->InternString("sys_chdir"),
235 context->storage->InternString("sys_time")}};
Lalit Magantid86161a2019-02-06 15:07:13 +0000236
237 // Build the lookup table for the strings inside ftrace events (e.g. the
238 // name of ftrace event fields and the names of their args).
239 for (size_t i = 0; i < GetDescriptorsSize(); i++) {
240 auto* descriptor = GetMessageDescriptorForId(i);
241 if (!descriptor->name) {
242 ftrace_message_strings_.emplace_back();
243 continue;
244 }
245
246 FtraceMessageStrings ftrace_strings;
247 ftrace_strings.message_name_id =
248 context->storage->InternString(descriptor->name);
249
Lalit Maganti3043fbd2019-02-07 10:21:50 +0000250 for (size_t fid = 0; fid <= descriptor->max_field_id; fid++) {
Lalit Magantid86161a2019-02-06 15:07:13 +0000251 const auto& field = descriptor->fields[fid];
252 if (!field.name)
253 continue;
254 ftrace_strings.field_name_ids[fid] =
255 context->storage->InternString(field.name);
256 }
257 ftrace_message_strings_.emplace_back(ftrace_strings);
258 }
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100259}
Lalit Maganti93b76362018-06-01 03:03:58 +0100260
Primiano Tucci0d72a312018-08-07 14:42:45 +0100261ProtoTraceParser::~ProtoTraceParser() = default;
262
Lalit Maganti85ca4a82018-12-07 17:28:02 +0000263void ProtoTraceParser::ParseTracePacket(int64_t ts, TraceBlobView packet) {
Primiano Tuccid933d912018-09-04 09:15:07 +0100264 ProtoDecoder decoder(packet.data(), packet.length());
Lalit Maganti93b76362018-06-01 03:03:58 +0100265
Lalit Magantidf3e9262018-06-04 17:45:00 +0100266 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
267 switch (fld.id) {
Primiano Tuccid933d912018-09-04 09:15:07 +0100268 case protos::TracePacket::kProcessTreeFieldNumber: {
269 const size_t fld_off = packet.offset_of(fld.data());
270 ParseProcessTree(packet.slice(fld_off, fld.size()));
Isabelle Taylord80932a2018-06-19 17:00:47 +0100271 break;
Primiano Tuccid933d912018-09-04 09:15:07 +0100272 }
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700273 case protos::TracePacket::kProcessStatsFieldNumber: {
274 const size_t fld_off = packet.offset_of(fld.data());
275 ParseProcessStats(ts, packet.slice(fld_off, fld.size()));
276 break;
277 }
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100278 case protos::TracePacket::kSysStatsFieldNumber: {
279 const size_t fld_off = packet.offset_of(fld.data());
280 ParseSysStats(ts, packet.slice(fld_off, fld.size()));
281 break;
282 }
Primiano Tuccib86e9ca2018-12-03 20:20:11 +0100283 case protos::TracePacket::kBatteryFieldNumber: {
284 const size_t fld_off = packet.offset_of(fld.data());
285 ParseBatteryCounters(ts, packet.slice(fld_off, fld.size()));
286 break;
287 }
Primiano Tucci0e38a142019-01-07 20:51:09 +0000288 case protos::TracePacket::kTraceStatsFieldNumber: {
289 const size_t fld_off = packet.offset_of(fld.data());
290 ParseTraceStats(packet.slice(fld_off, fld.size()));
291 break;
292 }
293 case protos::TracePacket::kFtraceStatsFieldNumber: {
294 const size_t fld_off = packet.offset_of(fld.data());
295 ParseFtraceStats(packet.slice(fld_off, fld.size()));
296 break;
297 }
Primiano Tuccia270f012019-01-07 20:01:00 +0000298 case protos::TracePacket::kClockSnapshotFieldNumber: {
299 const size_t fld_off = packet.offset_of(fld.data());
300 ParseClockSnapshot(packet.slice(fld_off, fld.size()));
301 break;
302 }
Primiano Tucci2c761ef2019-01-07 20:20:46 +0000303 case protos::TracePacket::kAndroidLogFieldNumber: {
304 const size_t fld_off = packet.offset_of(fld.data());
305 ParseAndroidLogPacket(packet.slice(fld_off, fld.size()));
306 break;
307 }
Hector Dearmandd639792019-01-31 15:04:59 +0000308 case protos::TracePacket::kProfilePacketFieldNumber: {
309 const size_t fld_off = packet.offset_of(fld.data());
310 ParseProfilePacket(packet.slice(fld_off, fld.size()));
311 break;
312 }
Lalit Magantidf3e9262018-06-04 17:45:00 +0100313 default:
314 break;
315 }
316 }
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +0000317 // TODO(lalitm): maybe move this to the flush method in the trace processor
318 // once we have it. This may reduce performance in the ArgsTracker though so
319 // needs to be handled carefully.
320 context_->args_tracker->Flush();
321
Lalit Magantidf3e9262018-06-04 17:45:00 +0100322 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
323}
324
Lalit Maganti85ca4a82018-12-07 17:28:02 +0000325void ProtoTraceParser::ParseSysStats(int64_t ts, TraceBlobView stats) {
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100326 ProtoDecoder decoder(stats.data(), stats.length());
327 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
328 switch (fld.id) {
329 case protos::SysStats::kMeminfoFieldNumber: {
330 const size_t fld_off = stats.offset_of(fld.data());
331 ParseMemInfo(ts, stats.slice(fld_off, fld.size()));
332 break;
333 }
334 case protos::SysStats::kVmstatFieldNumber: {
335 const size_t fld_off = stats.offset_of(fld.data());
336 ParseVmStat(ts, stats.slice(fld_off, fld.size()));
337 break;
338 }
339 case protos::SysStats::kCpuStatFieldNumber: {
340 const size_t fld_off = stats.offset_of(fld.data());
341 ParseCpuTimes(ts, stats.slice(fld_off, fld.size()));
342 break;
343 }
344 case protos::SysStats::kNumIrqFieldNumber: {
345 const size_t fld_off = stats.offset_of(fld.data());
346 ParseIrqCount(ts, stats.slice(fld_off, fld.size()),
347 /*is_softirq=*/false);
348 break;
349 }
350 case protos::SysStats::kNumSoftirqFieldNumber: {
351 const size_t fld_off = stats.offset_of(fld.data());
352 ParseIrqCount(ts, stats.slice(fld_off, fld.size()),
353 /*is_softirq=*/true);
354 break;
355 }
356 case protos::SysStats::kNumForksFieldNumber: {
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100357 context_->event_tracker->PushCounter(
Primiano Tucci5403e4f2018-11-27 10:07:03 +0000358 ts, fld.as_uint32(), num_forks_name_id_, 0, RefType::kRefNoRef);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100359 break;
360 }
361 case protos::SysStats::kNumIrqTotalFieldNumber: {
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100362 context_->event_tracker->PushCounter(
Primiano Tucci5403e4f2018-11-27 10:07:03 +0000363 ts, fld.as_uint32(), num_irq_total_name_id_, 0, RefType::kRefNoRef);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100364 break;
365 }
366 case protos::SysStats::kNumSoftirqTotalFieldNumber: {
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100367 context_->event_tracker->PushCounter(ts, fld.as_uint32(),
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100368 num_softirq_total_name_id_, 0,
Primiano Tucci5403e4f2018-11-27 10:07:03 +0000369 RefType::kRefNoRef);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100370 break;
371 }
372 default:
373 break;
374 }
375 }
376}
Lalit Maganti85ca4a82018-12-07 17:28:02 +0000377void ProtoTraceParser::ParseIrqCount(int64_t ts,
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100378 TraceBlobView irq,
379 bool is_soft) {
380 ProtoDecoder decoder(irq.data(), irq.length());
381 uint32_t key = 0;
382 uint32_t value = 0;
383 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
384 switch (fld.id) {
385 case protos::SysStats::InterruptCount::kIrqFieldNumber:
386 key = fld.as_uint32();
387 break;
388 case protos::SysStats::InterruptCount::kCountFieldNumber:
389 value = fld.as_uint32();
390 break;
391 }
392 }
Primiano Tucci5403e4f2018-11-27 10:07:03 +0000393 RefType ref_type = is_soft ? RefType::kRefIrq : RefType::kRefSoftIrq;
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100394 StringId name_id = is_soft ? num_irq_name_id_ : num_softirq_name_id_;
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100395 context_->event_tracker->PushCounter(ts, value, name_id, key, ref_type);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100396}
397
Lalit Maganti85ca4a82018-12-07 17:28:02 +0000398void ProtoTraceParser::ParseMemInfo(int64_t ts, TraceBlobView mem) {
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100399 ProtoDecoder decoder(mem.data(), mem.length());
400 uint32_t key = 0;
401 uint32_t value = 0;
402 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
403 switch (fld.id) {
404 case protos::SysStats::MeminfoValue::kKeyFieldNumber:
405 key = fld.as_uint32();
406 break;
407 case protos::SysStats::MeminfoValue::kValueFieldNumber:
408 value = fld.as_uint32();
409 break;
410 }
411 }
412 if (PERFETTO_UNLIKELY(key >= meminfo_strs_id_.size())) {
413 PERFETTO_ELOG("MemInfo key %d is not recognized.", key);
Primiano Tucci0e38a142019-01-07 20:51:09 +0000414 context_->storage->IncrementStats(stats::meminfo_unknown_keys);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100415 return;
416 }
Ioannis Ilkos5ef15b42019-01-08 10:57:52 +0000417 // /proc/meminfo counters are in kB, convert to bytes
418 context_->event_tracker->PushCounter(ts, value * 1024L, meminfo_strs_id_[key],
419 0, RefType::kRefNoRef);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100420}
421
Lalit Maganti85ca4a82018-12-07 17:28:02 +0000422void ProtoTraceParser::ParseVmStat(int64_t ts, TraceBlobView stat) {
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100423 ProtoDecoder decoder(stat.data(), stat.length());
424 uint32_t key = 0;
425 uint32_t value = 0;
426 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
427 switch (fld.id) {
428 case protos::SysStats::VmstatValue::kKeyFieldNumber:
429 key = fld.as_uint32();
430 break;
431 case protos::SysStats::VmstatValue::kValueFieldNumber:
432 value = fld.as_uint32();
433 break;
434 }
435 }
436 if (PERFETTO_UNLIKELY(key >= vmstat_strs_id_.size())) {
437 PERFETTO_ELOG("VmStat key %d is not recognized.", key);
Primiano Tucci0e38a142019-01-07 20:51:09 +0000438 context_->storage->IncrementStats(stats::vmstat_unknown_keys);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100439 return;
440 }
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100441 context_->event_tracker->PushCounter(ts, value, vmstat_strs_id_[key], 0,
Primiano Tucci5403e4f2018-11-27 10:07:03 +0000442 RefType::kRefNoRef);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100443}
444
Lalit Maganti85ca4a82018-12-07 17:28:02 +0000445void ProtoTraceParser::ParseCpuTimes(int64_t ts, TraceBlobView cpu_times) {
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100446 ProtoDecoder decoder(cpu_times.data(), cpu_times.length());
Lalit Maganti85ca4a82018-12-07 17:28:02 +0000447 uint64_t raw_cpu = 0;
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100448 uint32_t value = 0;
449 // Speculate on CPU being first.
450 constexpr auto kCpuFieldTag = protozero::proto_utils::MakeTagVarInt(
451 protos::SysStats::CpuTimes::kCpuIdFieldNumber);
452 if (cpu_times.length() > 2 && cpu_times.data()[0] == kCpuFieldTag &&
453 cpu_times.data()[1] < 0x80) {
Lalit Maganti85ca4a82018-12-07 17:28:02 +0000454 raw_cpu = cpu_times.data()[1];
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100455 } else {
456 if (!PERFETTO_LIKELY((
457 decoder.FindIntField<protos::SysStats::CpuTimes::kCpuIdFieldNumber>(
Lalit Maganti85ca4a82018-12-07 17:28:02 +0000458 &raw_cpu)))) {
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100459 PERFETTO_ELOG("CPU field not found in CpuTimes");
Primiano Tucci0e38a142019-01-07 20:51:09 +0000460 context_->storage->IncrementStats(stats::invalid_cpu_times);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100461 return;
462 }
463 }
464
Lalit Maganti85ca4a82018-12-07 17:28:02 +0000465 int64_t cpu = static_cast<int64_t>(raw_cpu);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100466 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
467 switch (fld.id) {
468 case protos::SysStats::CpuTimes::kUserNsFieldNumber: {
469 value = fld.as_uint32();
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100470 context_->event_tracker->PushCounter(ts, value, cpu_times_user_ns_id_,
Primiano Tucci5403e4f2018-11-27 10:07:03 +0000471 cpu, RefType::kRefCpuId);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100472 break;
473 }
474 case protos::SysStats::CpuTimes::kUserIceNsFieldNumber: {
475 value = fld.as_uint32();
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100476 context_->event_tracker->PushCounter(
Primiano Tucci5403e4f2018-11-27 10:07:03 +0000477 ts, value, cpu_times_user_ice_ns_id_, cpu, RefType::kRefCpuId);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100478 break;
479 }
480 case protos::SysStats::CpuTimes::kSystemModeNsFieldNumber: {
481 value = fld.as_uint32();
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100482 context_->event_tracker->PushCounter(
Primiano Tucci5403e4f2018-11-27 10:07:03 +0000483 ts, value, cpu_times_system_mode_ns_id_, cpu, RefType::kRefCpuId);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100484 break;
485 }
486 case protos::SysStats::CpuTimes::kIdleNsFieldNumber: {
487 value = fld.as_uint32();
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100488 context_->event_tracker->PushCounter(ts, value, cpu_times_idle_ns_id_,
Primiano Tucci5403e4f2018-11-27 10:07:03 +0000489 cpu, RefType::kRefCpuId);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100490 break;
491 }
492 case protos::SysStats::CpuTimes::kIoWaitNsFieldNumber: {
493 value = fld.as_uint32();
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100494 context_->event_tracker->PushCounter(
Primiano Tucci5403e4f2018-11-27 10:07:03 +0000495 ts, value, cpu_times_io_wait_ns_id_, cpu, RefType::kRefCpuId);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100496 break;
497 }
498 case protos::SysStats::CpuTimes::kIrqNsFieldNumber: {
499 value = fld.as_uint32();
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100500 context_->event_tracker->PushCounter(ts, value, cpu_times_irq_ns_id_,
Primiano Tucci5403e4f2018-11-27 10:07:03 +0000501 cpu, RefType::kRefCpuId);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100502 break;
503 }
504 case protos::SysStats::CpuTimes::kSoftirqNsFieldNumber: {
505 value = fld.as_uint32();
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100506 context_->event_tracker->PushCounter(
Primiano Tucci5403e4f2018-11-27 10:07:03 +0000507 ts, value, cpu_times_softirq_ns_id_, cpu, RefType::kRefCpuId);
Isabelle Taylor54ce7052018-10-01 14:00:15 +0100508 break;
509 }
510 default:
511 break;
512 }
513 }
514}
515
Primiano Tuccid933d912018-09-04 09:15:07 +0100516void ProtoTraceParser::ParseProcessTree(TraceBlobView pstree) {
517 ProtoDecoder decoder(pstree.data(), pstree.length());
Isabelle Taylord80932a2018-06-19 17:00:47 +0100518
Isabelle Taylord80932a2018-06-19 17:00:47 +0100519 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
Primiano Tuccid933d912018-09-04 09:15:07 +0100520 const size_t fld_off = pstree.offset_of(fld.data());
Isabelle Taylord80932a2018-06-19 17:00:47 +0100521 switch (fld.id) {
Primiano Tuccid933d912018-09-04 09:15:07 +0100522 case protos::ProcessTree::kProcessesFieldNumber: {
523 ParseProcess(pstree.slice(fld_off, fld.size()));
Isabelle Taylord80932a2018-06-19 17:00:47 +0100524 break;
Primiano Tuccid933d912018-09-04 09:15:07 +0100525 }
526 case protos::ProcessTree::kThreadsFieldNumber: {
527 ParseThread(pstree.slice(fld_off, fld.size()));
Isabelle Taylord80932a2018-06-19 17:00:47 +0100528 break;
Primiano Tuccid933d912018-09-04 09:15:07 +0100529 }
Isabelle Taylord80932a2018-06-19 17:00:47 +0100530 default:
531 break;
532 }
533 }
534 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
535}
536
Lalit Maganti85ca4a82018-12-07 17:28:02 +0000537void ProtoTraceParser::ParseProcessStats(int64_t ts, TraceBlobView stats) {
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700538 ProtoDecoder decoder(stats.data(), stats.length());
539
540 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
541 const size_t fld_off = stats.offset_of(fld.data());
542 switch (fld.id) {
Lalit Maganti6820abc2019-01-21 11:12:23 +0000543 case protos::ProcessStats::kProcessesFieldNumber: {
Lalit Maganti41c98922019-01-23 19:35:58 +0000544 ParseProcessStatsProcess(ts, stats.slice(fld_off, fld.size()));
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700545 break;
546 }
547 default:
548 break;
549 }
550 }
551 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
552}
553
Lalit Maganti41c98922019-01-23 19:35:58 +0000554void ProtoTraceParser::ParseProcessStatsProcess(int64_t ts,
555 TraceBlobView proc_stat) {
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700556 ProtoDecoder decoder(proc_stat.data(), proc_stat.length());
557 uint32_t pid = 0;
Lalit Maganti41c98922019-01-23 19:35:58 +0000558
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700559 // Maps a process counter field it to its value.
560 // E.g., 4 := 1024 -> "mem.rss.anon" := 1024.
Lalit Maganti41c98922019-01-23 19:35:58 +0000561 std::array<int64_t, kProcStatsProcessSize> counter_values{};
562 std::array<bool, kProcStatsProcessSize> has_counter{};
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700563
564 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
565 switch (fld.id) {
Lalit Maganti6820abc2019-01-21 11:12:23 +0000566 case protos::ProcessStats::Process::kPidFieldNumber:
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700567 pid = fld.as_uint32();
568 break;
Lalit Maganti41c98922019-01-23 19:35:58 +0000569 default: {
570 bool is_counter_field = fld.id < has_counter.size() &&
571 proc_stats_process_names_[fld.id] != 0;
572 if (is_counter_field) {
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700573 // Memory counters are in KB, keep values in bytes in the trace
574 // processor.
Lalit Maganti41c98922019-01-23 19:35:58 +0000575 counter_values[fld.id] =
576 fld.id == protos::ProcessStats::Process::kOomScoreAdjFieldNumber
577 ? fld.as_int64()
578 : fld.as_int64() * 1024;
579 has_counter[fld.id] = true;
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700580 } else {
Primiano Tucci0e38a142019-01-07 20:51:09 +0000581 context_->storage->IncrementStats(stats::proc_stat_unknown_counters);
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700582 }
Lalit Maganti41c98922019-01-23 19:35:58 +0000583 break;
584 }
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700585 }
586 }
587
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700588 // Skip field_id 0 (invalid) and 1 (pid).
589 for (size_t field_id = 2; field_id < counter_values.size(); field_id++) {
590 if (!has_counter[field_id])
591 continue;
592
593 // Lookup the interned string id from the field name using the
Lalit Maganti41c98922019-01-23 19:35:58 +0000594 // pre-cached |proc_stats_process_names_| map.
595 StringId name = proc_stats_process_names_[field_id];
596 int64_t value = counter_values[field_id];
597
598 UniquePid upid = context_->process_tracker->UpdateProcess(pid);
599 context_->event_tracker->PushCounter(ts, value, name, upid,
600 RefType::kRefUpid);
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700601 }
602
603 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
604}
605
Primiano Tuccid933d912018-09-04 09:15:07 +0100606void ProtoTraceParser::ParseThread(TraceBlobView thread) {
607 ProtoDecoder decoder(thread.data(), thread.length());
Isabelle Taylord80932a2018-06-19 17:00:47 +0100608 uint32_t tid = 0;
609 uint32_t tgid = 0;
Isabelle Taylord80932a2018-06-19 17:00:47 +0100610 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
611 switch (fld.id) {
612 case protos::ProcessTree::Thread::kTidFieldNumber:
613 tid = fld.as_uint32();
614 break;
615 case protos::ProcessTree::Thread::kTgidFieldNumber:
616 tgid = fld.as_uint32();
617 break;
Isabelle Taylord80932a2018-06-19 17:00:47 +0100618 default:
619 break;
620 }
621 }
Isabelle Taylora0a22972018-08-03 12:06:12 +0100622 context_->process_tracker->UpdateThread(tid, tgid);
Isabelle Taylord80932a2018-06-19 17:00:47 +0100623
624 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
625}
626
Primiano Tuccid933d912018-09-04 09:15:07 +0100627void ProtoTraceParser::ParseProcess(TraceBlobView process) {
628 ProtoDecoder decoder(process.data(), process.length());
629
Isabelle Taylord80932a2018-06-19 17:00:47 +0100630 uint32_t pid = 0;
Lalit Maganti08884242019-02-19 12:28:32 +0000631 uint32_t ppid = 0;
Primiano Tucci2da5d2e2018-08-10 14:23:31 +0100632 base::StringView process_name;
Primiano Tuccid933d912018-09-04 09:15:07 +0100633
Isabelle Taylord80932a2018-06-19 17:00:47 +0100634 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
635 switch (fld.id) {
636 case protos::ProcessTree::Process::kPidFieldNumber:
637 pid = fld.as_uint32();
638 break;
Lalit Maganti08884242019-02-19 12:28:32 +0000639 case protos::ProcessTree::Process::kPpidFieldNumber:
640 ppid = fld.as_uint32();
641 break;
Isabelle Taylord80932a2018-06-19 17:00:47 +0100642 case protos::ProcessTree::Process::kCmdlineFieldNumber:
Primiano Tucci711de1f2019-03-04 11:11:33 +0000643 if (process_name.empty()) // cmdline is a repeated field.
Primiano Tucci2da5d2e2018-08-10 14:23:31 +0100644 process_name = fld.as_string();
Isabelle Taylord80932a2018-06-19 17:00:47 +0100645 break;
646 default:
647 break;
648 }
649 }
Primiano Tucci711de1f2019-03-04 11:11:33 +0000650
Lalit Maganti08884242019-02-19 12:28:32 +0000651 context_->process_tracker->UpdateProcess(pid, ppid, process_name);
Isabelle Taylord80932a2018-06-19 17:00:47 +0100652 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
653}
654
Primiano Tuccid933d912018-09-04 09:15:07 +0100655void ProtoTraceParser::ParseFtracePacket(uint32_t cpu,
Lalit Maganti85ca4a82018-12-07 17:28:02 +0000656 int64_t timestamp,
Primiano Tuccid933d912018-09-04 09:15:07 +0100657 TraceBlobView ftrace) {
658 ProtoDecoder decoder(ftrace.data(), ftrace.length());
Lalit Maganti1d915a62019-01-07 12:10:42 +0000659 uint64_t raw_pid = 0;
660 if (!PERFETTO_LIKELY(
661 (decoder.FindIntField<protos::FtraceEvent::kPidFieldNumber>(
662 &raw_pid)))) {
663 PERFETTO_ELOG("Pid field not found in ftrace packet");
664 return;
665 }
666 uint32_t pid = static_cast<uint32_t>(raw_pid);
667
Lalit Magantidf3e9262018-06-04 17:45:00 +0100668 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
Lalit Maganti1d915a62019-01-07 12:10:42 +0000669 bool is_metadata_field =
670 fld.id == protos::FtraceEvent::kPidFieldNumber ||
671 fld.id == protos::FtraceEvent::kTimestampFieldNumber;
672 if (is_metadata_field)
673 continue;
674
675 const size_t fld_off = ftrace.offset_of(fld.data());
676 if (fld.id == protos::FtraceEvent::kGenericFieldNumber) {
Lalit Magantie87cc812019-01-10 15:20:06 +0000677 ParseGenericFtrace(timestamp, cpu, pid,
678 ftrace.slice(fld_off, fld.size()));
Lalit Magantibeb73712019-02-08 11:28:09 +0000679 } else if (fld.id != protos::FtraceEvent::kSchedSwitchFieldNumber) {
Lalit Magantie87cc812019-01-10 15:20:06 +0000680 ParseTypedFtraceToRaw(fld.id, timestamp, cpu, pid,
Lalit Maganti1d915a62019-01-07 12:10:42 +0000681 ftrace.slice(fld_off, fld.size()));
682 }
683
Lalit Magantidf3e9262018-06-04 17:45:00 +0100684 switch (fld.id) {
Primiano Tuccid933d912018-09-04 09:15:07 +0100685 case protos::FtraceEvent::kSchedSwitchFieldNumber: {
Primiano Tuccid933d912018-09-04 09:15:07 +0100686 ParseSchedSwitch(cpu, timestamp, ftrace.slice(fld_off, fld.size()));
Lalit Magantidf3e9262018-06-04 17:45:00 +0100687 break;
Primiano Tuccid933d912018-09-04 09:15:07 +0100688 }
Lalit Maganti369ea3c2019-03-05 11:09:42 +0000689 case protos::FtraceEvent::kSchedWakeup: {
690 ParseSchedWakeup(timestamp, ftrace.slice(fld_off, fld.size()));
691 break;
692 }
Isabelle Taylor14674d42018-09-07 11:33:11 +0100693 case protos::FtraceEvent::kCpuFrequency: {
Isabelle Taylor14674d42018-09-07 11:33:11 +0100694 ParseCpuFreq(timestamp, ftrace.slice(fld_off, fld.size()));
695 break;
696 }
Hector Dearman7b794cc2018-11-30 14:35:30 +0000697 case protos::FtraceEvent::kCpuIdle: {
Hector Dearman7b794cc2018-11-30 14:35:30 +0000698 ParseCpuIdle(timestamp, ftrace.slice(fld_off, fld.size()));
699 break;
700 }
Hector Dearman947f12a2018-09-11 16:50:36 +0100701 case protos::FtraceEvent::kPrintFieldNumber: {
Lalit Magantide6267f2018-11-08 12:35:34 +0000702 ParsePrint(cpu, timestamp, pid, ftrace.slice(fld_off, fld.size()));
Hector Dearman947f12a2018-09-11 16:50:36 +0100703 break;
704 }
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100705 case protos::FtraceEvent::kRssStatFieldNumber: {
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100706 ParseRssStat(timestamp, pid, ftrace.slice(fld_off, fld.size()));
707 break;
708 }
709 case protos::FtraceEvent::kIonHeapGrow: {
Primiano Tucci90cdc852018-12-21 10:29:44 +0100710 ParseIonHeapGrowOrShrink(timestamp, pid,
711 ftrace.slice(fld_off, fld.size()), true);
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100712 break;
713 }
714 case protos::FtraceEvent::kIonHeapShrink: {
Primiano Tucci90cdc852018-12-21 10:29:44 +0100715 ParseIonHeapGrowOrShrink(timestamp, pid,
716 ftrace.slice(fld_off, fld.size()), false);
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100717 break;
718 }
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000719 case protos::FtraceEvent::kSignalGenerate: {
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000720 ParseSignalGenerate(timestamp, ftrace.slice(fld_off, fld.size()));
721 break;
722 }
723 case protos::FtraceEvent::kSignalDeliver: {
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000724 ParseSignalDeliver(timestamp, pid, ftrace.slice(fld_off, fld.size()));
725 break;
726 }
Lalit Maganti66ed7ad2019-01-11 16:47:26 +0000727 case protos::FtraceEvent::kLowmemoryKill: {
728 ParseLowmemoryKill(timestamp, ftrace.slice(fld_off, fld.size()));
729 break;
730 }
Primiano Tucci44231042018-12-06 21:34:32 +0000731 case protos::FtraceEvent::kOomScoreAdjUpdate: {
Primiano Tucci44231042018-12-06 21:34:32 +0000732 ParseOOMScoreAdjUpdate(timestamp, ftrace.slice(fld_off, fld.size()));
733 break;
734 }
Lalit Magantia824c332019-01-23 17:55:58 +0000735 case protos::FtraceEvent::kMmEventRecordFieldNumber: {
736 ParseMmEventRecordField(timestamp, pid,
737 ftrace.slice(fld_off, fld.size()));
738 break;
739 }
Hector Dearmanbd6cd472019-02-13 16:42:52 +0000740 case protos::FtraceEvent::kSysEnterFieldNumber: {
741 ParseSysEvent(timestamp, pid, true, ftrace.slice(fld_off, fld.size()));
742 break;
743 }
Primiano Tucci711de1f2019-03-04 11:11:33 +0000744 case protos::FtraceEvent::kSysExitFieldNumber: {
Hector Dearmanbd6cd472019-02-13 16:42:52 +0000745 ParseSysEvent(timestamp, pid, false, ftrace.slice(fld_off, fld.size()));
746 break;
747 }
Primiano Tucci711de1f2019-03-04 11:11:33 +0000748 case protos::FtraceEvent::kTaskNewtaskFieldNumber: {
749 ParseTaskNewTask(timestamp, pid, ftrace.slice(fld_off, fld.size()));
750 break;
751 }
752 case protos::FtraceEvent::kTaskRenameFieldNumber: {
753 ParseTaskRename(timestamp, ftrace.slice(fld_off, fld.size()));
754 break;
755 }
Lalit Magantidf3e9262018-06-04 17:45:00 +0100756 default:
757 break;
758 }
759 }
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +0000760 // TODO(lalitm): maybe move this to the flush method in the trace processor
761 // once we have it. This may reduce performance in the ArgsTracker though so
762 // needs to be handled carefully.
763 context_->args_tracker->Flush();
764
Lalit Magantidf3e9262018-06-04 17:45:00 +0100765 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
766}
767
Lalit Maganti85ca4a82018-12-07 17:28:02 +0000768void ProtoTraceParser::ParseSignalDeliver(int64_t timestamp,
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000769 uint32_t pid,
770 TraceBlobView view) {
771 ProtoDecoder decoder(view.data(), view.length());
772 uint32_t sig = 0;
773 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
774 switch (fld.id) {
775 case protos::SignalDeliverFtraceEvent::kSigFieldNumber:
776 sig = fld.as_uint32();
777 break;
778 }
779 }
780 auto* instants = context_->storage->mutable_instants();
781 UniqueTid utid = context_->process_tracker->UpdateThread(timestamp, pid, 0);
782 instants->AddInstantEvent(timestamp, signal_deliver_id_, sig, utid,
Primiano Tucci5403e4f2018-11-27 10:07:03 +0000783 RefType::kRefUtid);
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000784}
785
Isabelle Taylor0996dbf2018-11-07 11:33:38 +0000786// This event has both the pid of the thread that sent the signal and the
787// destination of the signal. Currently storing the pid of the destination.
Lalit Maganti85ca4a82018-12-07 17:28:02 +0000788void ProtoTraceParser::ParseSignalGenerate(int64_t timestamp,
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000789 TraceBlobView view) {
790 ProtoDecoder decoder(view.data(), view.length());
791 uint32_t pid = 0;
792 uint32_t sig = 0;
793 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
794 switch (fld.id) {
795 case protos::SignalGenerateFtraceEvent::kPidFieldNumber:
796 pid = fld.as_uint32();
797 break;
798 case protos::SignalGenerateFtraceEvent::kSigFieldNumber:
799 sig = fld.as_uint32();
800 break;
801 }
802 }
803 auto* instants = context_->storage->mutable_instants();
804 UniqueTid utid = context_->process_tracker->UpdateThread(timestamp, pid, 0);
805 instants->AddInstantEvent(timestamp, signal_generate_id_, sig, utid,
Primiano Tucci5403e4f2018-11-27 10:07:03 +0000806 RefType::kRefUtid);
Isabelle Taylorc8c11202018-11-05 11:36:22 +0000807}
808
Lalit Maganti85ca4a82018-12-07 17:28:02 +0000809void ProtoTraceParser::ParseLowmemoryKill(int64_t timestamp,
Isabelle Taylor0996dbf2018-11-07 11:33:38 +0000810 TraceBlobView view) {
811 // TODO(taylori): Store the pagecache_size, pagecache_limit and free fields
812 // in an args table
813 ProtoDecoder decoder(view.data(), view.length());
814 uint32_t pid = 0;
815 base::StringView comm;
816 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
817 switch (fld.id) {
818 case protos::LowmemoryKillFtraceEvent::kPidFieldNumber:
819 pid = fld.as_uint32();
820 break;
821 case protos::LowmemoryKillFtraceEvent::kCommFieldNumber:
822 comm = fld.as_string();
823 break;
824 }
825 }
Lalit Maganti66ed7ad2019-01-11 16:47:26 +0000826
Isabelle Taylor0996dbf2018-11-07 11:33:38 +0000827 // Storing the pid of the event that is lmk-ed.
Lalit Maganti66ed7ad2019-01-11 16:47:26 +0000828 auto* instants = context_->storage->mutable_instants();
Lalit Maganti94c522b2019-01-15 00:03:15 +0000829 UniquePid upid = context_->process_tracker->UpdateProcess(pid);
Lalit Magantia93cce32019-02-06 17:45:02 +0000830 uint32_t row = instants->AddInstantEvent(timestamp, lmk_id_, 0, upid,
831 RefType::kRefUtidLookupUpid);
Lalit Maganti66ed7ad2019-01-11 16:47:26 +0000832
833 // Store the comm as an arg.
834 RowId row_id = TraceStorage::CreateRowId(TableId::kInstants, row);
835 auto comm_id = context_->storage->InternString(comm);
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +0000836 context_->args_tracker->AddArg(row_id, comm_name_id_, comm_name_id_,
837 Variadic::String(comm_id));
Isabelle Taylor0996dbf2018-11-07 11:33:38 +0000838}
839
Lalit Maganti85ca4a82018-12-07 17:28:02 +0000840void ProtoTraceParser::ParseRssStat(int64_t timestamp,
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100841 uint32_t pid,
842 TraceBlobView view) {
843 ProtoDecoder decoder(view.data(), view.length());
Primiano Tuccibc560992018-12-06 19:11:45 +0000844 const auto kRssStatUnknown = static_cast<uint32_t>(rss_members_.size()) - 1;
845 uint32_t member = kRssStatUnknown;
Primiano Tuccidbe49832018-12-18 19:37:04 +0000846 int64_t size = 0;
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100847 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
848 switch (fld.id) {
849 case protos::RssStatFtraceEvent::kMemberFieldNumber:
850 member = fld.as_uint32();
851 break;
852 case protos::RssStatFtraceEvent::kSizeFieldNumber:
Primiano Tuccidbe49832018-12-18 19:37:04 +0000853 size = fld.as_int64();
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100854 break;
855 }
856 }
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700857 if (member >= rss_members_.size()) {
Primiano Tucci0e38a142019-01-07 20:51:09 +0000858 context_->storage->IncrementStats(stats::rss_stat_unknown_keys);
Primiano Tuccibc560992018-12-06 19:11:45 +0000859 member = kRssStatUnknown;
Primiano Tuccic9d4a8b2018-10-30 20:19:01 -0700860 }
Lalit Maganti6d2edf62018-11-08 16:36:35 +0000861
Ioannis Ilkos81bd0ea2019-02-14 15:16:26 +0000862 if (size >= 0) {
863 UniqueTid utid = context_->process_tracker->UpdateThread(timestamp, pid, 0);
864
865 context_->event_tracker->PushCounter(timestamp, size, rss_members_[member],
866 utid, RefType::kRefUtidLookupUpid);
867 } else {
868 context_->storage->IncrementStats(stats::rss_stat_negative_size);
869 }
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100870 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
871}
872
Primiano Tucci90cdc852018-12-21 10:29:44 +0100873void ProtoTraceParser::ParseIonHeapGrowOrShrink(int64_t timestamp,
874 uint32_t pid,
875 TraceBlobView view,
876 bool grow) {
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100877 ProtoDecoder decoder(view.data(), view.length());
Primiano Tucci90cdc852018-12-21 10:29:44 +0100878 int64_t total_bytes = 0;
879 int64_t change_bytes = 0;
880 StringId global_name_id = ion_total_unknown_id_;
881 StringId change_name_id = ion_change_unknown_id_;
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100882 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
883 switch (fld.id) {
884 case protos::IonHeapGrowFtraceEvent::kTotalAllocatedFieldNumber:
Primiano Tucci90cdc852018-12-21 10:29:44 +0100885 total_bytes = fld.as_int64();
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100886 break;
Primiano Tucci90cdc852018-12-21 10:29:44 +0100887 case protos::IonHeapGrowFtraceEvent::kLenFieldNumber:
888 change_bytes = fld.as_int64() * (grow ? 1 : -1);
889 break;
890 case protos::IonHeapGrowFtraceEvent::kHeapNameFieldNumber: {
891 char counter_name[255];
892 base::StringView heap_name = fld.as_string();
893 snprintf(counter_name, sizeof(counter_name), "mem.ion.%.*s",
894 int(heap_name.size()), heap_name.data());
895 global_name_id = context_->storage->InternString(counter_name);
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100896
Primiano Tucci90cdc852018-12-21 10:29:44 +0100897 snprintf(counter_name, sizeof(counter_name), "mem.ion_change.%.*s",
898 int(heap_name.size()), heap_name.data());
899 change_name_id = context_->storage->InternString(counter_name);
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100900 break;
Primiano Tucci90cdc852018-12-21 10:29:44 +0100901 }
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100902 }
903 }
Primiano Tucci90cdc852018-12-21 10:29:44 +0100904 // Push the global counter.
905 context_->event_tracker->PushCounter(timestamp, total_bytes, global_name_id,
906 0, RefType::kRefNoRef);
907
908 // Push the change counter.
909 // TODO(b/121331269): these should really be instant events. For now we
Primiano Tuccicd37b4d2018-12-21 16:33:32 +0100910 // manually reset them to 0 after 1ns.
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100911 UniqueTid utid = context_->process_tracker->UpdateThread(timestamp, pid, 0);
Primiano Tucci90cdc852018-12-21 10:29:44 +0100912 context_->event_tracker->PushCounter(timestamp, change_bytes, change_name_id,
913 utid, RefType::kRefUtid);
Primiano Tuccicd37b4d2018-12-21 16:33:32 +0100914 context_->event_tracker->PushCounter(timestamp + 1, 0, change_name_id, utid,
915 RefType::kRefUtid);
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100916 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
Primiano Tucci90cdc852018-12-21 10:29:44 +0100917
918 // We are reusing the same function for ion_heap_grow and ion_heap_shrink.
919 // It is fine as the arguments are the same, but we need to be sure that the
920 // protobuf field id for both are the same.
921 static_assert(
922 protos::IonHeapGrowFtraceEvent::kTotalAllocatedFieldNumber ==
923 protos::IonHeapShrinkFtraceEvent::kTotalAllocatedFieldNumber &&
924 protos::IonHeapGrowFtraceEvent::kLenFieldNumber ==
925 protos::IonHeapShrinkFtraceEvent::kLenFieldNumber &&
926 protos::IonHeapGrowFtraceEvent::kHeapNameFieldNumber ==
927 protos::IonHeapShrinkFtraceEvent::kHeapNameFieldNumber,
928 "field mismatch");
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100929}
930
Lalit Maganti85ca4a82018-12-07 17:28:02 +0000931void ProtoTraceParser::ParseCpuFreq(int64_t timestamp, TraceBlobView view) {
Isabelle Taylor14674d42018-09-07 11:33:11 +0100932 ProtoDecoder decoder(view.data(), view.length());
933
Isabelle Taylor15314ea2018-09-19 11:35:19 +0100934 uint32_t cpu_affected = 0;
Isabelle Taylor14674d42018-09-07 11:33:11 +0100935 uint32_t new_freq = 0;
936 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
937 switch (fld.id) {
938 case protos::CpuFrequencyFtraceEvent::kCpuIdFieldNumber:
Isabelle Taylor15314ea2018-09-19 11:35:19 +0100939 cpu_affected = fld.as_uint32();
Isabelle Taylor14674d42018-09-07 11:33:11 +0100940 break;
941 case protos::CpuFrequencyFtraceEvent::kStateFieldNumber:
942 new_freq = fld.as_uint32();
943 break;
944 }
945 }
Isabelle Taylora97c5f52018-10-23 17:36:12 +0100946 context_->event_tracker->PushCounter(timestamp, new_freq, cpu_freq_name_id_,
Primiano Tucci5403e4f2018-11-27 10:07:03 +0000947 cpu_affected, RefType::kRefCpuId);
Isabelle Taylor14674d42018-09-07 11:33:11 +0100948 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
949}
950
Lalit Maganti85ca4a82018-12-07 17:28:02 +0000951void ProtoTraceParser::ParseCpuIdle(int64_t timestamp, TraceBlobView view) {
Hector Dearman7b794cc2018-11-30 14:35:30 +0000952 ProtoDecoder decoder(view.data(), view.length());
953
954 uint32_t cpu_affected = 0;
955 uint32_t new_state = 0;
956 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
957 switch (fld.id) {
958 case protos::CpuIdleFtraceEvent::kCpuIdFieldNumber:
959 cpu_affected = fld.as_uint32();
960 break;
961 case protos::CpuIdleFtraceEvent::kStateFieldNumber:
962 new_state = fld.as_uint32();
963 break;
964 }
965 }
966 context_->event_tracker->PushCounter(timestamp, new_state, cpu_idle_name_id_,
967 cpu_affected, RefType::kRefCpuId);
968 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
969}
970
Primiano Tucci7e330292018-08-24 19:10:52 +0200971void ProtoTraceParser::ParseSchedSwitch(uint32_t cpu,
Lalit Maganti85ca4a82018-12-07 17:28:02 +0000972 int64_t timestamp,
Primiano Tuccid933d912018-09-04 09:15:07 +0100973 TraceBlobView sswitch) {
974 ProtoDecoder decoder(sswitch.data(), sswitch.length());
975
Lalit Magantibeb73712019-02-08 11:28:09 +0000976 base::StringView prev_comm;
Lalit Magantidf3e9262018-06-04 17:45:00 +0100977 uint32_t prev_pid = 0;
Lalit Magantibeb73712019-02-08 11:28:09 +0000978 int32_t prev_prio = 0;
Lalit Maganti4af8dd82019-01-16 23:10:21 +0000979 int64_t prev_state = 0;
Lalit Magantifde29042018-10-04 13:28:52 +0100980 base::StringView next_comm;
Lalit Magantidf3e9262018-06-04 17:45:00 +0100981 uint32_t next_pid = 0;
Lalit Maganti4af8dd82019-01-16 23:10:21 +0000982 int32_t next_prio = 0;
Lalit Magantidf3e9262018-06-04 17:45:00 +0100983 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
984 switch (fld.id) {
985 case protos::SchedSwitchFtraceEvent::kPrevPidFieldNumber:
986 prev_pid = fld.as_uint32();
987 break;
Lalit Maganti35622b72018-06-06 12:03:11 +0100988 case protos::SchedSwitchFtraceEvent::kPrevStateFieldNumber:
Lalit Maganti4af8dd82019-01-16 23:10:21 +0000989 prev_state = fld.as_int64();
Lalit Maganti35622b72018-06-06 12:03:11 +0100990 break;
Lalit Magantibeb73712019-02-08 11:28:09 +0000991 case protos::SchedSwitchFtraceEvent::kPrevCommFieldNumber:
992 prev_comm = fld.as_string();
993 break;
994 case protos::SchedSwitchFtraceEvent::kPrevPrioFieldNumber:
995 prev_prio = fld.as_int32();
996 break;
Lalit Magantidf3e9262018-06-04 17:45:00 +0100997 case protos::SchedSwitchFtraceEvent::kNextPidFieldNumber:
998 next_pid = fld.as_uint32();
999 break;
Lalit Magantifde29042018-10-04 13:28:52 +01001000 case protos::SchedSwitchFtraceEvent::kNextCommFieldNumber:
1001 next_comm = fld.as_string();
1002 break;
Lalit Maganti4af8dd82019-01-16 23:10:21 +00001003 case protos::SchedSwitchFtraceEvent::kNextPrioFieldNumber:
1004 next_prio = fld.as_int32();
1005 break;
Lalit Magantidf3e9262018-06-04 17:45:00 +01001006 default:
1007 break;
1008 }
1009 }
Lalit Magantibeb73712019-02-08 11:28:09 +00001010 context_->event_tracker->PushSchedSwitch(cpu, timestamp, prev_pid, prev_comm,
1011 prev_prio, prev_state, next_pid,
1012 next_comm, next_prio);
Lalit Magantidf3e9262018-06-04 17:45:00 +01001013 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
1014}
1015
Lalit Maganti369ea3c2019-03-05 11:09:42 +00001016void ProtoTraceParser::ParseSchedWakeup(int64_t timestamp,
1017 TraceBlobView sswitch) {
1018 ProtoDecoder decoder(sswitch.data(), sswitch.length());
1019
1020 base::StringView comm;
1021 uint32_t wakee_pid = 0;
1022 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
1023 switch (fld.id) {
1024 case protos::SchedWakeupFtraceEvent::kCommFieldNumber:
1025 comm = fld.as_string();
1026 break;
1027 case protos::SchedWakeupFtraceEvent::kPidFieldNumber:
1028 wakee_pid = fld.as_uint32();
1029 break;
1030 }
1031 }
1032 StringId name_id = context_->storage->InternString(comm);
1033 auto utid =
1034 context_->process_tracker->UpdateThread(timestamp, wakee_pid, name_id);
1035 context_->storage->mutable_instants()->AddInstantEvent(
1036 timestamp, sched_wakeup_name_id_, 0 /* value */, utid, RefType::kRefUtid);
1037 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
1038}
1039
Primiano Tucci711de1f2019-03-04 11:11:33 +00001040void ProtoTraceParser::ParseTaskNewTask(int64_t timestamp,
1041 uint32_t source_tid,
1042 TraceBlobView event) {
1043 ProtoDecoder decoder(event.data(), event.length());
1044 uint32_t clone_flags = 0;
1045 uint32_t new_tid = 0;
1046 StringId new_comm = 0;
1047
1048 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
1049 switch (fld.id) {
1050 case protos::TaskNewtaskFtraceEvent::kCloneFlagsFieldNumber:
1051 clone_flags = fld.as_uint32();
1052 break;
1053 case protos::TaskNewtaskFtraceEvent::kPidFieldNumber:
1054 new_tid = fld.as_uint32();
1055 break;
1056 case protos::TaskNewtaskFtraceEvent::kCommFieldNumber:
1057 new_comm = context_->storage->InternString(fld.as_string());
1058 break;
1059 default:
1060 break;
1061 }
1062 }
1063
1064 auto* proc_tracker = context_->process_tracker.get();
1065
1066 // task_newtask is raised both in the case of a new process creation (fork()
1067 // family) and thread creation (clone(CLONE_THREAD, ...)).
1068 static const uint32_t kCloneThread = 0x00010000; // From kernel's sched.h.
1069 if ((clone_flags & kCloneThread) == 0) {
1070 // This is a plain-old fork() or equivalent.
1071 proc_tracker->StartNewProcess(timestamp, new_tid);
1072 return;
1073 }
1074
1075 // This is a pthread_create or similar. Bind the two threads together, so
1076 // they get resolved to the same process.
1077 auto source_utid = proc_tracker->UpdateThread(timestamp, source_tid, 0);
1078 auto new_utid = proc_tracker->StartNewThread(timestamp, new_tid, new_comm);
1079 proc_tracker->AssociateThreads(source_utid, new_utid);
1080}
1081
1082void ProtoTraceParser::ParseTaskRename(int64_t timestamp, TraceBlobView event) {
1083 ProtoDecoder decoder(event.data(), event.length());
1084 uint32_t tid = 0;
1085 StringId comm = 0;
1086
1087 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
1088 switch (fld.id) {
1089 case protos::TaskRenameFtraceEvent::kPidFieldNumber:
1090 tid = fld.as_uint32();
1091 break;
1092 case protos::TaskRenameFtraceEvent::kNewcommFieldNumber:
1093 comm = context_->storage->InternString(fld.as_string());
1094 break;
1095 default:
1096 break;
1097 }
1098 }
1099
1100 context_->process_tracker->UpdateThread(timestamp, tid, comm);
1101}
1102
Hector Dearman947f12a2018-09-11 16:50:36 +01001103void ProtoTraceParser::ParsePrint(uint32_t,
Lalit Maganti85ca4a82018-12-07 17:28:02 +00001104 int64_t timestamp,
Lalit Magantide6267f2018-11-08 12:35:34 +00001105 uint32_t pid,
Hector Dearman947f12a2018-09-11 16:50:36 +01001106 TraceBlobView print) {
1107 ProtoDecoder decoder(print.data(), print.length());
1108
1109 base::StringView buf{};
1110 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
1111 if (fld.id == protos::PrintFtraceEvent::kBufFieldNumber) {
1112 buf = fld.as_string();
1113 break;
1114 }
1115 }
1116
1117 SystraceTracePoint point{};
1118 if (!ParseSystraceTracePoint(buf, &point))
1119 return;
1120
Hector Dearman947f12a2018-09-11 16:50:36 +01001121 switch (point.phase) {
1122 case 'B': {
1123 StringId name_id = context_->storage->InternString(point.name);
Ioannis Ilkos21a76182019-01-28 14:05:01 +00001124 context_->slice_tracker->BeginAndroid(timestamp, pid, point.tgid,
Lalit Magantide6267f2018-11-08 12:35:34 +00001125 0 /*cat_id*/, name_id);
Hector Dearman947f12a2018-09-11 16:50:36 +01001126 break;
1127 }
1128
1129 case 'E': {
Ioannis Ilkos21a76182019-01-28 14:05:01 +00001130 context_->slice_tracker->EndAndroid(timestamp, pid, point.tgid);
Hector Dearman947f12a2018-09-11 16:50:36 +01001131 break;
1132 }
Isabelle Taylor31e04402018-09-19 12:13:25 +01001133
1134 case 'C': {
Lalit Maganti94c522b2019-01-15 00:03:15 +00001135 // LMK events from userspace are hacked as counter events with the "value"
1136 // of the counter representing the pid of the killed process which is
1137 // reset to 0 once the kill is complete.
1138 // Homogenise this with kernel LMK events as an instant event, ignoring
1139 // the resets to 0.
1140 if (point.name == "kill_one_process") {
1141 auto killed_pid = static_cast<uint32_t>(point.value);
1142 if (killed_pid != 0) {
1143 UniquePid killed_upid =
1144 context_->process_tracker->UpdateProcess(killed_pid);
1145 context_->storage->mutable_instants()->AddInstantEvent(
1146 timestamp, lmk_id_, 0, killed_upid, RefType::kRefUpid);
1147 }
Hector Dearman8caa2fc2019-01-29 13:56:30 +00001148 // TODO(lalitm): we should not add LMK events to the counters table
Lalit Maganti94c522b2019-01-15 00:03:15 +00001149 // once the UI has support for displaying instants.
1150 }
Hector Dearman8caa2fc2019-01-29 13:56:30 +00001151 // This is per upid on purpose. Some counters are pushed from arbitrary
1152 // threads but are really per process.
1153 UniquePid upid = context_->process_tracker->UpdateProcess(point.tgid);
Isabelle Taylor31e04402018-09-19 12:13:25 +01001154 StringId name_id = context_->storage->InternString(point.name);
Isabelle Taylora97c5f52018-10-23 17:36:12 +01001155 context_->event_tracker->PushCounter(timestamp, point.value, name_id,
Hector Dearman8caa2fc2019-01-29 13:56:30 +00001156 upid, RefType::kRefUpid);
Isabelle Taylor31e04402018-09-19 12:13:25 +01001157 }
Hector Dearman947f12a2018-09-11 16:50:36 +01001158 }
1159 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
1160}
1161
Lalit Maganti85ca4a82018-12-07 17:28:02 +00001162void ProtoTraceParser::ParseBatteryCounters(int64_t ts, TraceBlobView battery) {
Primiano Tuccib86e9ca2018-12-03 20:20:11 +01001163 ProtoDecoder decoder(battery.data(), battery.length());
1164 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
1165 switch (fld.id) {
1166 case protos::BatteryCounters::kChargeCounterUahFieldNumber:
1167 context_->event_tracker->PushCounter(
1168 ts, fld.as_int64(), batt_charge_id_, 0, RefType::kRefNoRef);
1169 break;
1170 case protos::BatteryCounters::kCapacityPercentFieldNumber:
1171 context_->event_tracker->PushCounter(
1172 ts, static_cast<double>(fld.as_float()), batt_capacity_id_, 0,
1173 RefType::kRefNoRef);
1174 break;
1175 case protos::BatteryCounters::kCurrentUaFieldNumber:
1176 context_->event_tracker->PushCounter(
1177 ts, fld.as_int64(), batt_current_id_, 0, RefType::kRefNoRef);
1178 break;
1179 case protos::BatteryCounters::kCurrentAvgUaFieldNumber:
1180 context_->event_tracker->PushCounter(
1181 ts, fld.as_int64(), batt_current_avg_id_, 0, RefType::kRefNoRef);
1182 break;
1183 default:
1184 break;
1185 }
1186 }
1187 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
1188}
1189
Lalit Maganti85ca4a82018-12-07 17:28:02 +00001190void ProtoTraceParser::ParseOOMScoreAdjUpdate(int64_t ts,
Primiano Tucci44231042018-12-06 21:34:32 +00001191 TraceBlobView oom_update) {
1192 ProtoDecoder decoder(oom_update.data(), oom_update.length());
1193 uint32_t pid = 0;
1194 int16_t oom_adj = 0;
1195
1196 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
1197 switch (fld.id) {
1198 case protos::OomScoreAdjUpdateFtraceEvent::kOomScoreAdjFieldNumber:
Primiano Tucci90cdc852018-12-21 10:29:44 +01001199 // TODO(b/120618641): The int16_t static cast is required because of
1200 // the linked negative varint encoding bug.
Primiano Tucci44231042018-12-06 21:34:32 +00001201 oom_adj = static_cast<int16_t>(fld.as_int32());
1202 break;
1203 case protos::OomScoreAdjUpdateFtraceEvent::kPidFieldNumber:
1204 pid = fld.as_uint32();
1205 break;
1206 case protos::OomScoreAdjUpdateFtraceEvent::kCommFieldNumber:
1207 default:
1208 break;
1209 }
1210 }
1211 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
1212
1213 UniquePid upid = context_->process_tracker->UpdateProcess(pid);
1214 context_->event_tracker->PushCounter(ts, oom_adj, oom_score_adj_id_, upid,
1215 RefType::kRefUpid);
1216}
1217
Lalit Magantia824c332019-01-23 17:55:58 +00001218void ProtoTraceParser::ParseMmEventRecordField(int64_t ts,
1219 uint32_t pid,
1220 TraceBlobView view) {
1221 ProtoDecoder decoder(view.data(), view.length());
1222
1223 uint32_t type = 0;
1224 uint32_t count = 0;
1225 uint32_t max_lat = 0;
1226 uint32_t avg_lat = 0;
1227 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
1228 switch (fld.id) {
1229 case protos::MmEventRecordFtraceEvent::kTypeFieldNumber:
1230 type = fld.as_uint32();
1231 break;
1232 case protos::MmEventRecordFtraceEvent::kCountFieldNumber:
1233 count = fld.as_uint32();
1234 break;
1235 case protos::MmEventRecordFtraceEvent::kMaxLatFieldNumber:
1236 max_lat = fld.as_uint32();
1237 break;
1238 case protos::MmEventRecordFtraceEvent::kAvgLatFieldNumber:
1239 avg_lat = fld.as_uint32();
1240 break;
1241 default:
1242 context_->storage->IncrementStats(stats::mm_unknown_counter);
1243 break;
1244 }
1245 }
1246
1247 UniqueTid utid = context_->process_tracker->UpdateThread(ts, pid, 0);
1248 if (type >= mm_event_counter_names_.size()) {
1249 context_->storage->IncrementStats(stats::mm_unknown_type);
1250 return;
1251 }
1252
1253 const auto& counter_names = mm_event_counter_names_[type];
1254 context_->event_tracker->PushCounter(ts, count, counter_names.count, utid,
1255 RefType::kRefUtidLookupUpid);
1256 context_->event_tracker->PushCounter(ts, max_lat, counter_names.max_lat, utid,
1257 RefType::kRefUtidLookupUpid);
1258 context_->event_tracker->PushCounter(ts, avg_lat, counter_names.avg_lat, utid,
1259 RefType::kRefUtidLookupUpid);
1260
1261 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
1262}
1263
Hector Dearmanbd6cd472019-02-13 16:42:52 +00001264void ProtoTraceParser::ParseSysEvent(int64_t ts,
1265 uint32_t pid,
1266 bool is_enter,
1267 TraceBlobView view) {
1268 ProtoDecoder decoder(view.data(), view.length());
1269
1270 uint32_t id = 0;
1271 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
1272 switch (fld.id) {
1273 case protos::SysEnterFtraceEvent::kIdFieldNumber:
1274 id = fld.as_uint32();
1275 break;
1276 }
1277 }
1278
1279 if (id >= sys_name_ids_.size()) {
1280 context_->storage->IncrementStats(stats::sys_unknown_sys_id);
1281 return;
1282 }
1283
1284 // We see two write sys calls around each userspace slice that is going via
1285 // trace_marker, this violates the assumption that userspace slices are
1286 // perfectly nested. For the moment ignore all write sys calls.
1287 // TODO(hjd): Remove this limitation.
1288 if (id == 4 /*sys_write*/)
1289 return;
1290
1291 StringId sys_name_id = sys_name_ids_[id];
1292 UniqueTid utid = context_->process_tracker->UpdateThread(ts, pid, 0);
1293 if (is_enter) {
1294 context_->slice_tracker->Begin(ts, utid, 0 /* cat */, sys_name_id);
1295 } else {
1296 context_->slice_tracker->End(ts, utid, 0 /* cat */, sys_name_id);
1297 }
1298
1299 // We are reusing the same function for sys_enter and sys_exit.
1300 // It is fine as the arguments are the same, but we need to be sure that the
1301 // protobuf field id for both are the same.
1302 static_assert(protos::SysEnterFtraceEvent::kIdFieldNumber ==
1303 protos::SysExitFtraceEvent::kIdFieldNumber,
1304 "field mismatch");
1305}
1306
Lalit Maganti1d915a62019-01-07 12:10:42 +00001307void ProtoTraceParser::ParseGenericFtrace(int64_t timestamp,
Lalit Magantie87cc812019-01-10 15:20:06 +00001308 uint32_t cpu,
Lalit Maganti1d915a62019-01-07 12:10:42 +00001309 uint32_t tid,
1310 TraceBlobView view) {
1311 ProtoDecoder decoder(view.data(), view.length());
1312
1313 base::StringView event_name;
1314 if (!PERFETTO_LIKELY((decoder.FindStringField<
1315 protos::GenericFtraceEvent::kEventNameFieldNumber>(
1316 &event_name)))) {
1317 PERFETTO_ELOG("Event name not found in generic ftrace packet");
1318 return;
1319 }
1320
1321 UniqueTid utid = context_->process_tracker->UpdateThread(timestamp, tid, 0);
1322 StringId event_id = context_->storage->InternString(std::move(event_name));
1323 RowId row_id = context_->storage->mutable_raw_events()->AddRawEvent(
Lalit Magantie87cc812019-01-10 15:20:06 +00001324 timestamp, event_id, cpu, utid);
Lalit Maganti1d915a62019-01-07 12:10:42 +00001325
1326 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
1327 switch (fld.id) {
1328 case protos::GenericFtraceEvent::kFieldFieldNumber:
1329 const size_t fld_off = view.offset_of(fld.data());
1330 ParseGenericFtraceField(row_id, view.slice(fld_off, fld.size()));
1331 break;
1332 }
1333 }
1334}
1335
1336void ProtoTraceParser::ParseGenericFtraceField(RowId generic_row_id,
1337 TraceBlobView view) {
1338 ProtoDecoder decoder(view.data(), view.length());
1339
1340 base::StringView field_name;
1341 if (!PERFETTO_LIKELY((decoder.FindStringField<
1342 protos::GenericFtraceEvent::Field::kNameFieldNumber>(
1343 &field_name)))) {
1344 PERFETTO_ELOG("Event name not found in generic ftrace packet");
1345 return;
1346 }
1347 auto field_name_id = context_->storage->InternString(std::move(field_name));
1348 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
1349 switch (fld.id) {
1350 case protos::GenericFtraceEvent::Field::kIntValue:
1351 case protos::GenericFtraceEvent::Field::kUintValue: {
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +00001352 context_->args_tracker->AddArg(generic_row_id, field_name_id,
1353 field_name_id,
1354 Variadic::Integer(fld.as_integer()));
Lalit Maganti1d915a62019-01-07 12:10:42 +00001355 break;
1356 }
1357 case protos::GenericFtraceEvent::Field::kStrValue: {
1358 StringId value = context_->storage->InternString(fld.as_string());
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +00001359 context_->args_tracker->AddArg(generic_row_id, field_name_id,
1360 field_name_id, Variadic::String(value));
Lalit Maganti1d915a62019-01-07 12:10:42 +00001361 }
1362 }
1363 }
1364}
1365
1366void ProtoTraceParser::ParseTypedFtraceToRaw(uint32_t ftrace_id,
1367 int64_t timestamp,
Lalit Magantie87cc812019-01-10 15:20:06 +00001368 uint32_t cpu,
Lalit Maganti1d915a62019-01-07 12:10:42 +00001369 uint32_t tid,
1370 TraceBlobView view) {
1371 ProtoDecoder decoder(view.data(), view.length());
1372 if (ftrace_id >= GetDescriptorsSize()) {
1373 PERFETTO_DLOG("Event with id: %d does not exist and cannot be parsed.",
1374 ftrace_id);
1375 return;
1376 }
Lalit Magantid86161a2019-02-06 15:07:13 +00001377
Lalit Maganti1d915a62019-01-07 12:10:42 +00001378 MessageDescriptor* m = GetMessageDescriptorForId(ftrace_id);
Lalit Magantid86161a2019-02-06 15:07:13 +00001379 const auto& message_strings = ftrace_message_strings_[ftrace_id];
Lalit Maganti1d915a62019-01-07 12:10:42 +00001380 UniqueTid utid = context_->process_tracker->UpdateThread(timestamp, tid, 0);
1381 RowId raw_event_id = context_->storage->mutable_raw_events()->AddRawEvent(
Lalit Magantid86161a2019-02-06 15:07:13 +00001382 timestamp, message_strings.message_name_id, cpu, utid);
Lalit Maganti1d915a62019-01-07 12:10:42 +00001383 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
1384 ProtoSchemaType type = m->fields[fld.id].type;
Lalit Magantid86161a2019-02-06 15:07:13 +00001385 StringId name_id = message_strings.field_name_ids[fld.id];
Lalit Maganti1d915a62019-01-07 12:10:42 +00001386 switch (type) {
1387 case ProtoSchemaType::kUint32:
1388 case ProtoSchemaType::kInt32:
1389 case ProtoSchemaType::kUint64:
1390 case ProtoSchemaType::kInt64:
1391 case ProtoSchemaType::kFixed64:
1392 case ProtoSchemaType::kFixed32:
1393 case ProtoSchemaType::kSfixed32:
1394 case ProtoSchemaType::kSfixed64:
1395 case ProtoSchemaType::kSint32:
1396 case ProtoSchemaType::kSint64:
1397 case ProtoSchemaType::kBool:
1398 case ProtoSchemaType::kEnum: {
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +00001399 context_->args_tracker->AddArg(raw_event_id, name_id, name_id,
1400 Variadic::Integer(fld.as_integer()));
Lalit Maganti1d915a62019-01-07 12:10:42 +00001401 break;
1402 }
1403 case ProtoSchemaType::kString:
1404 case ProtoSchemaType::kBytes: {
1405 StringId value = context_->storage->InternString(fld.as_string());
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +00001406 context_->args_tracker->AddArg(raw_event_id, name_id, name_id,
1407 Variadic::String(value));
Lalit Maganti1d915a62019-01-07 12:10:42 +00001408 break;
1409 }
1410 case ProtoSchemaType::kDouble:
1411 case ProtoSchemaType::kFloat: {
Lalit Maganti4fa7c6c2019-02-06 15:06:36 +00001412 context_->args_tracker->AddArg(raw_event_id, name_id, name_id,
1413 Variadic::Real(fld.as_real()));
Lalit Maganti1d915a62019-01-07 12:10:42 +00001414 break;
1415 }
1416 case ProtoSchemaType::kUnknown:
1417 case ProtoSchemaType::kGroup:
1418 case ProtoSchemaType::kMessage:
1419 PERFETTO_DLOG("Could not store %s as a field in args table.",
1420 ProtoSchemaToString(type));
1421 break;
1422 }
1423 }
1424}
1425
Primiano Tuccia270f012019-01-07 20:01:00 +00001426void ProtoTraceParser::ParseClockSnapshot(TraceBlobView packet) {
1427 ProtoDecoder decoder(packet.data(), packet.length());
1428 int64_t clock_boottime = 0;
1429 int64_t clock_monotonic = 0;
1430 int64_t clock_realtime = 0;
1431
1432 // This loop iterates over the "repeated Clock" entries.
1433 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
1434 switch (fld.id) {
1435 case protos::ClockSnapshot::kClocksFieldNumber: {
1436 const size_t fld_off = packet.offset_of(fld.data());
1437 auto clk = ParseClockField(packet.slice(fld_off, fld.size()));
1438 switch (clk.first) {
1439 case protos::ClockSnapshot::Clock::BOOTTIME:
1440 clock_boottime = clk.second;
1441 break;
1442 case protos::ClockSnapshot::Clock::REALTIME:
1443 clock_realtime = clk.second;
1444 break;
1445 case protos::ClockSnapshot::Clock::MONOTONIC:
1446 clock_monotonic = clk.second;
1447 break;
1448 }
1449 break;
1450 }
1451 default:
1452 break;
1453 }
1454 }
1455 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
1456
1457 // Usually these snapshots come all together.
1458 PERFETTO_DCHECK(clock_boottime > 0 && clock_monotonic > 0 &&
1459 clock_realtime > 0);
1460
1461 if (clock_boottime <= 0) {
1462 PERFETTO_ELOG("ClockSnapshot has an invalid BOOTTIME (%" PRId64 ")",
1463 clock_boottime);
Primiano Tucci0e38a142019-01-07 20:51:09 +00001464 context_->storage->IncrementStats(stats::invalid_clock_snapshots);
Primiano Tuccia270f012019-01-07 20:01:00 +00001465 return;
1466 }
1467
1468 auto* ct = context_->clock_tracker.get();
1469
1470 // |clock_boottime| is used as the reference trace time.
1471 ct->SyncClocks(ClockDomain::kBootTime, clock_boottime, clock_boottime);
1472
1473 if (clock_monotonic > 0)
1474 ct->SyncClocks(ClockDomain::kMonotonic, clock_monotonic, clock_boottime);
1475
1476 if (clock_realtime > 0)
1477 ct->SyncClocks(ClockDomain::kRealTime, clock_realtime, clock_boottime);
1478}
1479
1480std::pair<int, int64_t> ProtoTraceParser::ParseClockField(
1481 TraceBlobView packet) {
1482 ProtoDecoder decoder(packet.data(), packet.length());
1483 int type = protos::ClockSnapshot::Clock::UNKNOWN;
1484 int64_t value = -1;
1485
1486 // This loop iterates over the |type| and |timestamp| field of each
1487 // clock snapshot.
1488 for (auto fld = decoder.ReadField(); fld.id; fld = decoder.ReadField()) {
1489 switch (fld.id) {
1490 case protos::ClockSnapshot::Clock::kTypeFieldNumber:
1491 type = fld.as_int32();
1492 break;
1493 case protos::ClockSnapshot::Clock::kTimestampFieldNumber:
1494 value = fld.as_int64();
1495 break;
1496 }
1497 }
1498 return std::make_pair(type, value);
1499}
1500
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001501void ProtoTraceParser::ParseAndroidLogPacket(TraceBlobView packet) {
1502 ProtoDecoder decoder(packet.data(), packet.length());
1503 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
1504 switch (fld.id) {
1505 case protos::AndroidLogPacket::kEventsFieldNumber: {
1506 const size_t fld_off = packet.offset_of(fld.data());
1507 ParseAndroidLogEvent(packet.slice(fld_off, fld.size()));
1508 break;
1509 }
Primiano Tucci0e38a142019-01-07 20:51:09 +00001510 case protos::AndroidLogPacket::kStatsFieldNumber: {
1511 const size_t fld_off = packet.offset_of(fld.data());
1512 ParseAndroidLogStats(packet.slice(fld_off, fld.size()));
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001513 break;
Primiano Tucci0e38a142019-01-07 20:51:09 +00001514 }
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001515 }
1516 }
1517 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
1518}
1519
1520void ProtoTraceParser::ParseAndroidLogEvent(TraceBlobView event) {
1521 // TODO(primiano): Add events and non-stringified fields to the "raw" table.
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001522 ProtoDecoder decoder(event.data(), event.length());
1523 int64_t ts = 0;
1524 uint32_t pid = 0;
1525 uint32_t tid = 0;
1526 uint8_t prio = 0;
1527 StringId tag_id = 0;
1528 StringId msg_id = 0;
1529 char arg_msg[4096];
1530 char* arg_str = &arg_msg[0];
1531 *arg_str = '\0';
1532 auto arg_avail = [&arg_msg, &arg_str]() {
1533 return sizeof(arg_msg) - static_cast<size_t>(arg_str - arg_msg);
1534 };
1535
1536 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
1537 switch (fld.id) {
1538 case protos::AndroidLogPacket::LogEvent::kPidFieldNumber:
1539 pid = fld.as_uint32();
1540 break;
1541 case protos::AndroidLogPacket::LogEvent::kTidFieldNumber:
1542 tid = fld.as_uint32();
1543 break;
1544 case protos::AndroidLogPacket::LogEvent::kTimestampFieldNumber:
1545 ts = fld.as_int64();
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001546 break;
1547 case protos::AndroidLogPacket::LogEvent::kPrioFieldNumber:
1548 prio = static_cast<uint8_t>(fld.as_uint32());
1549 break;
1550 case protos::AndroidLogPacket::LogEvent::kTagFieldNumber:
1551 tag_id = context_->storage->InternString(fld.as_string());
1552 break;
1553 case protos::AndroidLogPacket::LogEvent::kMessageFieldNumber:
1554 msg_id = context_->storage->InternString(fld.as_string());
1555 break;
1556 case protos::AndroidLogPacket::LogEvent::kArgsFieldNumber: {
1557 const size_t fld_off = event.offset_of(fld.data());
1558 TraceBlobView arg_data = event.slice(fld_off, fld.size());
1559 ParseAndroidLogBinaryArg(std::move(arg_data), &arg_str, arg_avail());
1560 break;
1561 }
1562 default:
1563 break;
1564 }
1565 }
1566 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
1567
1568 if (prio == 0)
1569 prio = protos::AndroidLogPriority::PRIO_INFO;
1570
1571 if (arg_str != &arg_msg[0]) {
1572 PERFETTO_DCHECK(!msg_id);
1573 // Skip the first space char (" foo=1 bar=2" -> "foo=1 bar=2").
1574 msg_id = context_->storage->InternString(&arg_msg[1]);
1575 }
1576 UniquePid utid = tid ? context_->process_tracker->UpdateThread(tid, pid) : 0;
Hector Dearmanba43f602019-01-29 14:36:11 +00001577 base::Optional<int64_t> opt_trace_time =
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001578 context_->clock_tracker->ToTraceTime(ClockDomain::kRealTime, ts);
Hector Dearmanba43f602019-01-29 14:36:11 +00001579 if (!opt_trace_time)
1580 return;
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001581
1582 // Log events are NOT required to be sorted by trace_time. The virtual table
1583 // will take care of sorting on-demand.
Hector Dearmanba43f602019-01-29 14:36:11 +00001584 context_->storage->mutable_android_log()->AddLogEvent(
1585 opt_trace_time.value(), utid, prio, tag_id, msg_id);
Primiano Tucci2c761ef2019-01-07 20:20:46 +00001586}
1587
1588void ProtoTraceParser::ParseAndroidLogBinaryArg(TraceBlobView arg,
1589 char** str,
1590 size_t avail) {
1591 ProtoDecoder decoder(arg.data(), arg.length());
1592 for (auto fld = decoder.ReadField(); fld.id; fld = decoder.ReadField()) {
1593 switch (fld.id) {
1594 case protos::AndroidLogPacket::LogEvent::Arg::kNameFieldNumber: {
1595 base::StringView name = fld.as_string();
1596 *str += snprintf(*str, avail, " %.*s=", static_cast<int>(name.size()),
1597 name.data());
1598 break;
1599 }
1600 case protos::AndroidLogPacket::LogEvent::Arg::kStringValueFieldNumber: {
1601 base::StringView val = fld.as_string();
1602 *str += snprintf(*str, avail, "\"%.*s\"", static_cast<int>(val.size()),
1603 val.data());
1604 break;
1605 }
1606 case protos::AndroidLogPacket::LogEvent::Arg::kIntValueFieldNumber:
1607 *str += snprintf(*str, avail, "%" PRId64, fld.as_int64());
1608 break;
1609 case protos::AndroidLogPacket::LogEvent::Arg::kFloatValueFieldNumber:
1610 *str +=
1611 snprintf(*str, avail, "%f", static_cast<double>(fld.as_float()));
1612 break;
1613 }
1614 }
1615}
1616
Primiano Tucci0e38a142019-01-07 20:51:09 +00001617void ProtoTraceParser::ParseAndroidLogStats(TraceBlobView packet) {
1618 ProtoDecoder decoder(packet.data(), packet.length());
1619 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
1620 switch (fld.id) {
1621 case protos::AndroidLogPacket::Stats::kNumFailedFieldNumber:
1622 context_->storage->SetStats(stats::android_log_num_failed,
1623 fld.as_int64());
1624 break;
1625 case protos::AndroidLogPacket::Stats::kNumSkippedFieldNumber:
1626 context_->storage->SetStats(stats::android_log_num_skipped,
1627 fld.as_int64());
1628 break;
1629 case protos::AndroidLogPacket::Stats::kNumTotalFieldNumber:
1630 context_->storage->SetStats(stats::android_log_num_total,
1631 fld.as_int64());
1632 break;
1633 }
1634 }
1635 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
1636}
1637
1638void ProtoTraceParser::ParseTraceStats(TraceBlobView packet) {
1639 ProtoDecoder decoder(packet.data(), packet.length());
1640 int buf_num = 0;
1641 auto* storage = context_->storage.get();
1642 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
1643 switch (fld.id) {
1644 case protos::TraceStats::kProducersConnectedFieldNumber:
1645 storage->SetStats(stats::traced_producers_connected, fld.as_int64());
1646 break;
1647 case protos::TraceStats::kProducersSeenFieldNumber:
1648 storage->SetStats(stats::traced_producers_seen, fld.as_int64());
1649 break;
1650 case protos::TraceStats::kDataSourcesRegisteredFieldNumber:
1651 storage->SetStats(stats::traced_data_sources_registered,
1652 fld.as_int64());
1653 break;
1654 case protos::TraceStats::kDataSourcesSeenFieldNumber:
1655 storage->SetStats(stats::traced_data_sources_seen, fld.as_int64());
1656 break;
1657 case protos::TraceStats::kTracingSessionsFieldNumber:
1658 storage->SetStats(stats::traced_tracing_sessions, fld.as_int64());
1659 break;
1660 case protos::TraceStats::kTotalBuffersFieldNumber:
1661 storage->SetStats(stats::traced_total_buffers, fld.as_int64());
1662 break;
Eric Seckler2c72bd82019-02-08 15:01:34 +00001663 case protos::TraceStats::kChunksDiscardedFieldNumber:
1664 storage->SetStats(stats::traced_chunks_discarded, fld.as_int64());
1665 break;
1666 case protos::TraceStats::kPatchesDiscardedFieldNumber:
1667 storage->SetStats(stats::traced_patches_discarded, fld.as_int64());
1668 break;
Primiano Tucci0e38a142019-01-07 20:51:09 +00001669 case protos::TraceStats::kBufferStatsFieldNumber: {
1670 const size_t fld_off = packet.offset_of(fld.data());
1671 TraceBlobView buf_data = packet.slice(fld_off, fld.size());
1672 ProtoDecoder buf_d(buf_data.data(), buf_data.length());
1673 for (auto fld2 = buf_d.ReadField(); fld2.id; fld2 = buf_d.ReadField()) {
1674 switch (fld2.id) {
Eric Secklerbd8aae52019-01-28 08:57:31 +00001675 case protos::TraceStats::BufferStats::kBufferSizeFieldNumber:
1676 storage->SetIndexedStats(stats::traced_buf_buffer_size, buf_num,
1677 fld2.as_int64());
1678 break;
Primiano Tucci0e38a142019-01-07 20:51:09 +00001679 case protos::TraceStats::BufferStats::kBytesWrittenFieldNumber:
1680 storage->SetIndexedStats(stats::traced_buf_bytes_written, buf_num,
1681 fld2.as_int64());
1682 break;
Eric Secklerbd8aae52019-01-28 08:57:31 +00001683 case protos::TraceStats::BufferStats::kBytesOverwrittenFieldNumber:
1684 storage->SetIndexedStats(stats::traced_buf_bytes_overwritten,
1685 buf_num, fld2.as_int64());
1686 break;
1687 case protos::TraceStats::BufferStats::kBytesReadFieldNumber:
1688 storage->SetIndexedStats(stats::traced_buf_bytes_read, buf_num,
1689 fld2.as_int64());
1690 break;
1691 case protos::TraceStats::BufferStats::
1692 kPaddingBytesWrittenFieldNumber:
1693 storage->SetIndexedStats(stats::traced_buf_padding_bytes_written,
1694 buf_num, fld2.as_int64());
1695 break;
1696 case protos::TraceStats::BufferStats::
1697 kPaddingBytesClearedFieldNumber:
1698 storage->SetIndexedStats(stats::traced_buf_padding_bytes_cleared,
1699 buf_num, fld2.as_int64());
1700 break;
Primiano Tucci0e38a142019-01-07 20:51:09 +00001701 case protos::TraceStats::BufferStats::kChunksWrittenFieldNumber:
1702 storage->SetIndexedStats(stats::traced_buf_chunks_written,
1703 buf_num, fld2.as_int64());
1704 break;
Stephen Nuskod13fdf82019-01-15 11:22:58 +00001705 case protos::TraceStats::BufferStats::kChunksRewrittenFieldNumber:
1706 storage->SetIndexedStats(stats::traced_buf_chunks_rewritten,
1707 buf_num, fld2.as_int64());
1708 break;
Primiano Tucci0e38a142019-01-07 20:51:09 +00001709 case protos::TraceStats::BufferStats::kChunksOverwrittenFieldNumber:
1710 storage->SetIndexedStats(stats::traced_buf_chunks_overwritten,
1711 buf_num, fld2.as_int64());
1712 break;
Primiano Tuccib45a69b2019-01-25 14:32:10 +00001713 case protos::TraceStats::BufferStats::kChunksDiscardedFieldNumber:
1714 storage->SetIndexedStats(stats::traced_buf_chunks_discarded,
1715 buf_num, fld2.as_int64());
1716 break;
Eric Secklerbd8aae52019-01-28 08:57:31 +00001717 case protos::TraceStats::BufferStats::kChunksReadFieldNumber:
1718 storage->SetIndexedStats(stats::traced_buf_chunks_read, buf_num,
1719 fld2.as_int64());
1720 break;
Stephen Nuskod13fdf82019-01-15 11:22:58 +00001721 case protos::TraceStats::BufferStats::
1722 kChunksCommittedOutOfOrderFieldNumber:
1723 storage->SetIndexedStats(
1724 stats::traced_buf_chunks_committed_out_of_order, buf_num,
1725 fld2.as_int64());
1726 break;
Primiano Tucci0e38a142019-01-07 20:51:09 +00001727 case protos::TraceStats::BufferStats::kWriteWrapCountFieldNumber:
1728 storage->SetIndexedStats(stats::traced_buf_write_wrap_count,
1729 buf_num, fld2.as_int64());
1730 break;
1731 case protos::TraceStats::BufferStats::kPatchesSucceededFieldNumber:
1732 storage->SetIndexedStats(stats::traced_buf_patches_succeeded,
1733 buf_num, fld2.as_int64());
1734 break;
1735 case protos::TraceStats::BufferStats::kPatchesFailedFieldNumber:
1736 storage->SetIndexedStats(stats::traced_buf_patches_failed,
1737 buf_num, fld2.as_int64());
1738 break;
1739 case protos::TraceStats::BufferStats::
1740 kReadaheadsSucceededFieldNumber:
1741 storage->SetIndexedStats(stats::traced_buf_readaheads_succeeded,
1742 buf_num, fld2.as_int64());
1743 break;
1744 case protos::TraceStats::BufferStats::kReadaheadsFailedFieldNumber:
1745 storage->SetIndexedStats(stats::traced_buf_readaheads_failed,
1746 buf_num, fld2.as_int64());
1747 break;
1748 }
1749 } // for (buf_fld)
1750 buf_num++;
1751 break;
1752 }
1753 default:
1754 break;
1755 }
1756 }
1757 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
1758}
1759
1760void ProtoTraceParser::ParseFtraceStats(TraceBlobView packet) {
1761 ProtoDecoder decoder(packet.data(), packet.length());
1762 size_t phase = 0;
1763 auto* storage = context_->storage.get();
1764 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
1765 switch (fld.id) {
1766 case protos::FtraceStats::kPhaseFieldNumber:
1767 phase = fld.int_value == protos::FtraceStats_Phase_END_OF_TRACE ? 1 : 0;
1768
1769 // This code relies on the fact that each ftrace_cpu_XXX_end event is
1770 // just after the corresponding ftrace_cpu_XXX_begin event.
1771 static_assert(stats::ftrace_cpu_read_events_end -
1772 stats::ftrace_cpu_read_events_begin ==
1773 1 &&
1774 stats::ftrace_cpu_entries_end -
1775 stats::ftrace_cpu_entries_begin ==
1776 1,
1777 "ftrace_cpu_XXX stats definition are messed up");
1778 break;
1779 case protos::FtraceStats::kCpuStatsFieldNumber: {
1780 const size_t fld_off = packet.offset_of(fld.data());
1781 TraceBlobView cpu_data = packet.slice(fld_off, fld.size());
1782 ProtoDecoder cpu_d(cpu_data.data(), cpu_data.length());
1783 int cpu_num = -1;
1784 for (auto fld2 = cpu_d.ReadField(); fld2.id; fld2 = cpu_d.ReadField()) {
1785 switch (fld2.id) {
1786 case protos::FtraceCpuStats::kCpuFieldNumber:
1787 cpu_num = fld2.as_int32();
1788 break;
1789 case protos::FtraceCpuStats::kEntriesFieldNumber:
1790 storage->SetIndexedStats(stats::ftrace_cpu_entries_begin + phase,
1791 cpu_num, fld2.as_int64());
1792 break;
1793 case protos::FtraceCpuStats::kOverrunFieldNumber:
1794 storage->SetIndexedStats(stats::ftrace_cpu_overrun_begin + phase,
1795 cpu_num, fld2.as_int64());
1796 break;
1797 case protos::FtraceCpuStats::kCommitOverrunFieldNumber:
1798 storage->SetIndexedStats(
1799 stats::ftrace_cpu_commit_overrun_begin + phase, cpu_num,
1800 fld2.as_int64());
1801 break;
1802 case protos::FtraceCpuStats::kBytesReadFieldNumber:
1803 storage->SetIndexedStats(
1804 stats::ftrace_cpu_bytes_read_begin + phase, cpu_num,
1805 fld2.as_int64());
1806 break;
1807 case protos::FtraceCpuStats::kOldestEventTsFieldNumber:
1808 storage->SetIndexedStats(
1809 stats::ftrace_cpu_oldest_event_ts_begin + phase, cpu_num,
1810 static_cast<int64_t>(fld2.as_double() * 1e9));
1811 break;
1812 case protos::FtraceCpuStats::kNowTsFieldNumber:
1813 storage->SetIndexedStats(
1814 stats::ftrace_cpu_now_ts_begin + phase, cpu_num,
1815 static_cast<int64_t>(fld2.as_double() * 1e9));
1816 break;
1817 case protos::FtraceCpuStats::kDroppedEventsFieldNumber:
1818 storage->SetIndexedStats(
1819 stats::ftrace_cpu_dropped_events_begin + phase, cpu_num,
1820 fld2.as_int64());
1821 break;
1822 case protos::FtraceCpuStats::kReadEventsFieldNumber:
1823 storage->SetIndexedStats(
1824 stats::ftrace_cpu_read_events_begin + phase, cpu_num,
1825 fld2.as_int64());
1826 break;
1827 }
1828 } // for (buf_fld)
1829 break;
1830 }
1831 default:
1832 break;
1833 }
1834 }
1835 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
1836}
1837
Hector Dearmandd639792019-01-31 15:04:59 +00001838void ProtoTraceParser::ParseProfilePacket(TraceBlobView packet) {
1839 ProtoDecoder decoder(packet.data(), packet.length());
1840 for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
1841 switch (fld.id) {
1842 case protos::ProfilePacket::kStringsFieldNumber: {
1843 const size_t fld_off = packet.offset_of(fld.data());
1844 TraceBlobView nestedPacket = packet.slice(fld_off, fld.size());
1845 ProtoDecoder nested(nestedPacket.data(), nestedPacket.length());
1846 for (auto sub = nested.ReadField(); sub.id != 0;
1847 sub = nested.ReadField()) {
1848 switch (sub.id) {
1849 case protos::ProfilePacket::InternedString::kIdFieldNumber: {
1850 break;
1851 }
1852 case protos::ProfilePacket::InternedString::kStrFieldNumber: {
1853 context_->storage->InternString(sub.as_string());
1854 break;
1855 }
1856 }
1857 }
1858 break;
1859 }
1860 case protos::ProfilePacket::kFramesFieldNumber: {
1861 break;
1862 }
1863 case protos::ProfilePacket::kCallstacksFieldNumber: {
1864 break;
1865 }
1866 case protos::ProfilePacket::kMappingsFieldNumber: {
1867 break;
1868 }
1869 case protos::ProfilePacket::kProcessDumpsFieldNumber: {
1870 break;
1871 }
1872 case protos::ProfilePacket::kContinuedFieldNumber: {
1873 bool continued = fld.as_bool();
1874 base::ignore_result(continued);
1875 break;
1876 }
1877 case protos::ProfilePacket::kIndexFieldNumber: {
1878 int64_t index = fld.as_int64();
1879 base::ignore_result(index);
1880 break;
1881 }
1882 }
1883 }
1884 PERFETTO_DCHECK(decoder.IsEndOfBuffer());
1885}
1886
Lalit Maganti93b76362018-06-01 03:03:58 +01001887} // namespace trace_processor
1888} // namespace perfetto