blob: 52f033f3816e787e17241655fc208e07dac6aacd [file] [log] [blame]
Lalit Magantidfe69ca2018-10-30 12:18:23 +00001#!/usr/bin/python
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
16import argparse
17
18from google.protobuf import descriptor, descriptor_pb2, message_factory, reflection
19from google.protobuf.pyext import _message
20
Primiano Tucci711de1f2019-03-04 11:11:33 +000021CLONE_THREAD = 0x00010000
Lalit Maganti70f3b312020-01-22 11:17:42 +000022CLONE_VFORK = 0x00004000
23CLONE_VM = 0x00000100
Primiano Tucci711de1f2019-03-04 11:11:33 +000024
Lalit Magantidfe69ca2018-10-30 12:18:23 +000025
26class Trace(object):
Ryan Savitski261473a2019-07-18 23:10:13 +010027
Primiano Tucci711de1f2019-03-04 11:11:33 +000028 def __init__(self, trace):
29 self.trace = trace
30 self.proc_map = {}
Ioannis Ilkos20d5e8b2019-05-16 15:43:26 +010031 self.proc_map[0] = 'idle_thread'
Lalit Magantidfe69ca2018-10-30 12:18:23 +000032
Lalit Maganti1fad9e62019-12-19 14:02:37 +000033 def add_system_info(self, arch="", fingerprint=""):
Hector Dearmanf31a7032019-03-29 10:05:09 +000034 self.packet = self.trace.packet.add()
35 self.packet.system_info.utsname.machine = arch
Lalit Maganti1fad9e62019-12-19 14:02:37 +000036 self.packet.system_info.android_build_fingerprint = fingerprint
Hector Dearmanf31a7032019-03-29 10:05:09 +000037
Primiano Tucci711de1f2019-03-04 11:11:33 +000038 def add_ftrace_packet(self, cpu):
39 self.packet = self.trace.packet.add()
40 self.packet.ftrace_events.cpu = cpu
Lalit Magantidfe69ca2018-10-30 12:18:23 +000041
Simon MacMullen213968b2020-06-02 13:30:35 +010042 def add_packet(self, ts=None):
Silvia Vinyes37bddf42019-06-14 14:26:17 +010043 self.packet = self.trace.packet.add()
Simon MacMullen213968b2020-06-02 13:30:35 +010044 if ts is not None:
45 self.packet.timestamp = ts
Silvia Vinyes37bddf42019-06-14 14:26:17 +010046 return self.packet
47
Primiano Tucci711de1f2019-03-04 11:11:33 +000048 def __add_ftrace_event(self, ts, tid):
49 ftrace = self.packet.ftrace_events.event.add()
50 ftrace.timestamp = ts
51 ftrace.pid = tid
52 return ftrace
Lalit Maganti17d8f682018-12-07 14:25:17 +000053
Lalit Maganti697894f2019-12-23 14:32:13 +000054 def add_rss_stat(self, ts, tid, member, size, mm_id=None, curr=None):
Primiano Tucci711de1f2019-03-04 11:11:33 +000055 ftrace = self.__add_ftrace_event(ts, tid)
56 rss_stat = ftrace.rss_stat
57 rss_stat.member = member
58 rss_stat.size = size
Lalit Maganti697894f2019-12-23 14:32:13 +000059 if mm_id is not None:
60 rss_stat.mm_id = mm_id
61 if curr is not None:
62 rss_stat.curr = curr
Lalit Maganti17d8f682018-12-07 14:25:17 +000063
Ioannis Ilkosd8ebbbb2020-02-10 15:47:53 +000064 def add_ion_event(self, ts, tid, heap_name, len, size=0):
Ioannis Ilkosdb8b1cb2019-06-25 17:05:32 +010065 ftrace = self.__add_ftrace_event(ts, tid)
66 ion = ftrace.ion_heap_grow
67 ion.heap_name = heap_name
Ioannis Ilkosd8ebbbb2020-02-10 15:47:53 +000068 ion.len = len
Ioannis Ilkosdb8b1cb2019-06-25 17:05:32 +010069 ion.total_allocated = size
70
Primiano Tucci711de1f2019-03-04 11:11:33 +000071 def add_oom_score_update(self, ts, oom_score_adj, pid):
72 ftrace = self.__add_ftrace_event(ts, pid)
73 oom_score = ftrace.oom_score_adj_update
74 oom_score.comm = self.proc_map[pid]
75 oom_score.oom_score_adj = oom_score_adj
76 oom_score.pid = pid
Lalit Maganti17d8f682018-12-07 14:25:17 +000077
Ryan Savitski261473a2019-07-18 23:10:13 +010078 def add_sched(self,
79 ts,
80 prev_pid,
81 next_pid,
82 prev_comm=None,
83 next_comm=None,
84 prev_state=None):
Primiano Tucci711de1f2019-03-04 11:11:33 +000085 ftrace = self.__add_ftrace_event(ts, 0)
86 ss = ftrace.sched_switch
87 ss.prev_comm = prev_comm or self.proc_map[prev_pid]
88 ss.prev_pid = prev_pid
89 ss.next_pid = next_pid
90 ss.next_comm = next_comm or self.proc_map[next_pid]
Ioannis Ilkos20d5e8b2019-05-16 15:43:26 +010091 if prev_state:
92 if prev_state == 'R':
93 ss.prev_state = 0
Ioannis Ilkos38255f42019-05-17 11:07:24 +010094 elif prev_state == 'S':
95 ss.prev_state = 1
96 elif prev_state == 'U':
97 ss.prev_state = 2
Ioannis Ilkos20d5e8b2019-05-16 15:43:26 +010098 else:
99 raise Exception('Invalid prev state {}'.format(prev_state))
Lalit Maganti17d8f682018-12-07 14:25:17 +0000100
Primiano Tucci711de1f2019-03-04 11:11:33 +0000101 def add_cpufreq(self, ts, freq, cpu):
102 ftrace = self.__add_ftrace_event(ts, 0)
103 cpufreq = ftrace.cpu_frequency
104 cpufreq.state = freq
105 cpufreq.cpu_id = cpu
Lalit Maganti17d8f682018-12-07 14:25:17 +0000106
Primiano Tucci711de1f2019-03-04 11:11:33 +0000107 def add_kernel_lmk(self, ts, tid):
108 ftrace = self.__add_ftrace_event(ts, tid)
109 lowmemory_kill = ftrace.lowmemory_kill
110 lowmemory_kill.pid = tid
Lalit Magantidfe69ca2018-10-30 12:18:23 +0000111
Primiano Tucci711de1f2019-03-04 11:11:33 +0000112 def add_sys_enter(self, ts, tid, id):
113 ftrace = self.__add_ftrace_event(ts, tid)
114 sys_enter = ftrace.sys_enter
115 sys_enter.id = id
Lalit Magantidfe69ca2018-10-30 12:18:23 +0000116
Primiano Tucci711de1f2019-03-04 11:11:33 +0000117 def add_sys_exit(self, ts, tid, id, ret):
118 ftrace = self.__add_ftrace_event(ts, tid)
119 sys_exit = ftrace.sys_exit
120 sys_exit.id = id
121 sys_exit.ret = ret
Lalit Magantidfe69ca2018-10-30 12:18:23 +0000122
Primiano Tucci711de1f2019-03-04 11:11:33 +0000123 def add_newtask(self, ts, tid, new_tid, new_comm, flags):
124 ftrace = self.__add_ftrace_event(ts, tid)
125 newtask = ftrace.task_newtask
126 newtask.pid = new_tid
127 newtask.comm = new_comm
128 newtask.clone_flags = flags
Lalit Magantidfe69ca2018-10-30 12:18:23 +0000129
Lalit Maganti637589a2019-07-04 17:25:29 +0100130 def add_process_free(self, ts, tid, comm, prio):
Lalit Maganti161d1e62019-06-25 16:06:17 +0100131 ftrace = self.__add_ftrace_event(ts, tid)
Lalit Maganti637589a2019-07-04 17:25:29 +0100132 sched_process_free = ftrace.sched_process_free
133 sched_process_free.pid = tid
134 sched_process_free.comm = comm
135 sched_process_free.prio = prio
Lalit Maganti161d1e62019-06-25 16:06:17 +0100136
137 def add_rename(self, ts, tid, old_comm, new_comm, oom_score_adj):
138 ftrace = self.__add_ftrace_event(ts, tid)
139 task_rename = ftrace.task_rename
140 task_rename.pid = tid
141 task_rename.oldcomm = old_comm
142 task_rename.newcomm = new_comm
143 task_rename.oom_score_adj = oom_score_adj
144
Ioannis Ilkos20d5e8b2019-05-16 15:43:26 +0100145 def add_print(self, ts, tid, buf):
146 ftrace = self.__add_ftrace_event(ts, tid)
147 print_event = getattr(ftrace, 'print')
148 print_event.buf = buf
149
Ryan Savitski261473a2019-07-18 23:10:13 +0100150 def add_kmalloc(self, ts, tid, bytes_alloc, bytes_req, call_site, gfp_flags,
151 ptr):
152 ftrace = self.__add_ftrace_event(ts, tid)
153 kmalloc = ftrace.kmalloc
154 kmalloc.bytes_alloc = bytes_alloc
155 kmalloc.bytes_req = bytes_req
156 kmalloc.call_site = call_site
157 kmalloc.gfp_flags = gfp_flags
158 kmalloc.ptr = ptr
159
160 def add_kfree(self, ts, tid, call_site, ptr):
161 ftrace = self.__add_ftrace_event(ts, tid)
162 kfree = ftrace.kfree
163 kfree.call_site = call_site
164 kfree.ptr = ptr
165
Ioannis Ilkos3e5b9152019-06-17 19:09:58 +0100166 def add_atrace_counter(self, ts, pid, tid, buf, cnt):
167 self.add_print(ts, tid, 'C|{}|{}|{}'.format(pid, buf, cnt))
168
Ioannis Ilkos20d5e8b2019-05-16 15:43:26 +0100169 def add_atrace_begin(self, ts, tid, pid, buf):
170 self.add_print(ts, tid, 'B|{}|{}'.format(pid, buf))
171
172 def add_atrace_end(self, ts, tid, pid):
173 self.add_print(ts, tid, 'E|{}'.format(pid))
174
175 def add_atrace_async_begin(self, ts, tid, pid, buf):
176 self.add_print(ts, tid, 'S|{}|{}|0'.format(pid, buf))
177
178 def add_atrace_async_end(self, ts, tid, pid, buf):
179 self.add_print(ts, tid, 'F|{}|{}|0'.format(pid, buf))
180
Ioannis Ilkosfd554bc2019-11-16 01:14:57 +0000181 def add_process(self, pid, ppid, cmdline, uid=None):
Primiano Tucci711de1f2019-03-04 11:11:33 +0000182 process = self.packet.process_tree.processes.add()
183 process.pid = pid
184 process.ppid = ppid
185 process.cmdline.append(cmdline)
Ioannis Ilkosfd554bc2019-11-16 01:14:57 +0000186 if uid is not None:
187 process.uid = uid
Primiano Tucci711de1f2019-03-04 11:11:33 +0000188 self.proc_map[pid] = cmdline
Lalit Maganti6cf6edb2019-02-07 11:09:47 +0000189
Primiano Tucci711de1f2019-03-04 11:11:33 +0000190 def add_thread(self, tid, tgid, cmdline):
191 thread = self.packet.process_tree.threads.add()
192 thread.tid = tid
193 thread.tgid = tgid
194 self.proc_map[tid] = cmdline
Lalit Magantidfe69ca2018-10-30 12:18:23 +0000195
Lalit Maganti161d1e62019-06-25 16:06:17 +0100196 def add_battery_counters(self, ts, charge_uah, cap_prct, curr_ua,
197 curr_avg_ua):
Silvia Vinyesb39c77f2019-06-04 10:46:12 +0100198 self.packet = self.trace.packet.add()
199 self.packet.timestamp = ts
200 battery_count = self.packet.battery
201 battery_count.charge_counter_uah = charge_uah
202 battery_count.capacity_percent = cap_prct
203 battery_count.current_ua = curr_ua
204 battery_count.current_avg_ua = curr_avg_ua
205
Lalit Maganti161d1e62019-06-25 16:06:17 +0100206 def add_battery_counters_no_curr_ua(self, ts, charge_uah, cap_prct,
207 curr_avg_ua):
Silvia Vinyesb39c77f2019-06-04 10:46:12 +0100208 self.packet = self.trace.packet.add()
209 self.packet.timestamp = ts
210 battery_count = self.packet.battery
211 battery_count.charge_counter_uah = charge_uah
212 battery_count.capacity_percent = cap_prct
213 battery_count.current_avg_ua = curr_avg_ua
Lalit Magantidfe69ca2018-10-30 12:18:23 +0000214
Silvia Vinyes37bddf42019-06-14 14:26:17 +0100215 def add_power_rails_desc(self, index_val, name):
216 power_rails = self.packet.power_rails
217 descriptor = power_rails.rail_descriptor.add()
218 descriptor.index = index_val
219 descriptor.rail_name = name
220
221 def add_power_rails_data(self, ts, index_val, value):
222 power_rails = self.packet.power_rails
223 energy_data = power_rails.energy_data.add()
224 energy_data.index = index_val
225 energy_data.timestamp_ms = ts
226 energy_data.energy = value
227
Ioannis Ilkosf1835e32019-07-11 14:11:48 +0100228 def add_package_list(self, ts, name, uid, version_code):
229 packet = self.add_packet()
230 packet.timestamp = ts
231 plist = packet.packages_list
232 pinfo = plist.packages.add()
233 pinfo.name = name
234 pinfo.uid = uid
235 pinfo.version_code = version_code
236
Ioannis Ilkos94de58c2019-08-02 18:17:33 +0100237 def add_profile_packet(self, ts):
238 packet = self.add_packet()
239 packet.timestamp = ts
240 return packet.profile_packet
Ryan Savitski261473a2019-07-18 23:10:13 +0100241
Primiano Tucci6756fb02019-08-14 15:49:18 +0200242 def add_clock_snapshot(self, clocks, seq_id=None):
243 packet = self.add_packet()
244 if seq_id is not None:
245 packet.trusted_packet_sequence_id = seq_id
246 snap = self.packet.clock_snapshot
Primiano Tucci834fdc72019-10-04 11:33:44 +0100247 for k, v in clocks.iteritems():
Primiano Tucci6756fb02019-08-14 15:49:18 +0200248 clock = snap.clocks.add()
249 clock.clock_id = k
250 clock.timestamp = v
251
Pascal Muetschard98df2542019-08-28 13:12:54 -0700252 def add_gpu_counter_spec(self,
253 ts,
254 counter_id,
255 name,
256 description=None,
257 unit_numerators=[],
258 unit_denominators=[]):
259 packet = self.add_packet()
260 packet.timestamp = ts
261 gpu_counters = packet.gpu_counter_event
262 counter_desc = gpu_counters.counter_descriptor
263 spec = counter_desc.specs.add()
264 spec.counter_id = counter_id
265 spec.name = name
266 if description is not None:
267 spec.description = description
268 spec.numerator_units.extend(unit_numerators)
269 spec.denominator_units.extend(unit_denominators)
270
Primiano Tucci6756fb02019-08-14 15:49:18 +0200271 def add_gpu_counter(self, ts, counter_id, value, clock_id=None, seq_id=None):
272 packet = self.add_packet()
273 packet.timestamp = ts
274 if clock_id is not None:
275 packet.timestamp_clock_id = clock_id
276 if seq_id is not None:
277 packet.trusted_packet_sequence_id = seq_id
278 gpu_counters = self.packet.gpu_counter_event
279 gpu_counter = gpu_counters.counters.add()
280 gpu_counter.counter_id = counter_id
281 gpu_counter.int_value = value
282
Raymond Chiu5d526b82019-11-22 14:18:51 -0800283 def add_gpu_render_stages_hw_queue_spec(self, specs=[]):
284 packet = self.add_packet()
285 spec = self.packet.gpu_render_stage_event.specifications
286 for s in specs:
287 hw_queue = spec.hw_queue.add()
288 hw_queue.name = s.get('name', '')
Raymond Chiu6353cea2019-12-04 14:32:33 -0800289 if 'description' in s:
290 hw_queue.description = s['description']
Raymond Chiu5d526b82019-11-22 14:18:51 -0800291
292 def add_gpu_render_stages_stage_spec(self, specs=[]):
293 packet = self.add_packet()
294 spec = self.packet.gpu_render_stage_event.specifications
295 for s in specs:
296 stage = spec.stage.add()
297 stage.name = s.get('name', '')
Raymond Chiu6353cea2019-12-04 14:32:33 -0800298 if 'description' in s:
299 stage.description = s['description']
Raymond Chiu5d526b82019-11-22 14:18:51 -0800300
301 def add_gpu_render_stages(self,
302 ts,
303 event_id,
304 duration,
305 hw_queue_id,
306 stage_id,
307 context,
308 render_target_handle=None,
309 render_pass_handle=None,
310 command_buffer_handle=None,
311 submission_id=None,
312 extra_data={}):
313 packet = self.add_packet()
314 packet.timestamp = ts
315 render_stage = self.packet.gpu_render_stage_event
316 render_stage.event_id = event_id
317 render_stage.duration = duration
318 render_stage.hw_queue_id = hw_queue_id
319 render_stage.stage_id = stage_id
320 render_stage.context = context
321 if render_target_handle is not None:
322 render_stage.render_target_handle = render_target_handle
323 if render_pass_handle is not None:
324 render_stage.render_pass_handle = render_pass_handle
325 if command_buffer_handle is not None:
326 render_stage.command_buffer_handle = command_buffer_handle
327 if submission_id is not None:
328 render_stage.submission_id = submission_id
329 for key, value in extra_data.items():
330 data = render_stage.extra_data.add()
331 data.name = key
332 if value is not None:
333 data.value = value
334
Raymond Chiude6b3802019-11-22 16:54:58 -0800335 def add_vk_debug_marker(self, ts, pid, vk_device, obj_type, obj, obj_name):
Raymond Chiu5d526b82019-11-22 14:18:51 -0800336 packet = self.add_packet()
337 packet.timestamp = ts
338 debug_marker = (self.packet.vulkan_api_event.vk_debug_utils_object_name)
339 debug_marker.pid = pid
340 debug_marker.vk_device = vk_device
Raymond Chiude6b3802019-11-22 16:54:58 -0800341 debug_marker.object_type = obj_type
Raymond Chiu5d526b82019-11-22 14:18:51 -0800342 debug_marker.object = obj
343 debug_marker.object_name = obj_name
344
Raymond Chiuf2c48a12020-01-15 11:30:34 -0800345 def add_vk_queue_submit(self, ts, dur, pid, tid, vk_queue, vk_command_buffers,
346 submission_id):
347 packet = self.add_packet()
348 packet.timestamp = ts
349 submit = (self.packet.vulkan_api_event.vk_queue_submit)
350 submit.duration_ns = dur
351 submit.pid = pid
352 submit.tid = tid
353 for cmd in vk_command_buffers:
354 submit.vk_command_buffers.append(cmd)
355 submit.submission_id = submission_id
356
Raymond Chiuc612b7f2019-09-18 14:53:28 -0700357 def add_gpu_log(self, ts, severity, tag, message):
358 packet = self.add_packet()
359 packet.timestamp = ts
360 gpu_log = self.packet.gpu_log
361 gpu_log.severity = severity
362 gpu_log.tag = tag
363 gpu_log.log_message = message
364
Primiano Tucci834fdc72019-10-04 11:33:44 +0100365 def add_buffer_event_packet(self, ts, buffer_id, layer_name, frame_number,
366 event_type, duration):
Mikael Pessa7160ccc2019-07-25 11:19:26 -0700367 packet = self.add_packet()
368 packet.timestamp = ts
369 buffer_event = packet.graphics_frame_event.buffer_event
370 if buffer_id >= 0:
371 buffer_event.buffer_id = buffer_id
372 buffer_event.layer_name = layer_name
373 buffer_event.frame_number = frame_number
374 if event_type >= 0:
375 buffer_event.type = event_type
376 buffer_event.duration_ns = duration
Primiano Tucci6756fb02019-08-14 15:49:18 +0200377
Simon MacMullen213968b2020-06-02 13:30:35 +0100378 def add_cpu(self, freqs):
379 cpu = self.packet.cpu_info.cpus.add()
380 for freq in freqs:
381 cpu.frequencies.append(freq)
382
383 def add_process_stats(self, pid, freqs):
384 process = self.packet.process_stats.processes.add()
385 process.pid = pid
386 thread = process.threads.add()
387 thread.tid = pid * 10
388 for index in freqs:
389 thread.cpu_freq_indices.append(index)
390 thread.cpu_freq_ticks.append(freqs[index])
391
Primiano Tucci834fdc72019-10-04 11:33:44 +0100392
Lalit Magantidfe69ca2018-10-30 12:18:23 +0000393def create_trace():
Primiano Tucci711de1f2019-03-04 11:11:33 +0000394 parser = argparse.ArgumentParser()
395 parser.add_argument(
396 'trace_descriptor', type=str, help='location of trace descriptor')
397 args = parser.parse_args()
Lalit Magantidfe69ca2018-10-30 12:18:23 +0000398
Ryan Savitski261473a2019-07-18 23:10:13 +0100399 with open(args.trace_descriptor, 'rb') as t:
Primiano Tucci711de1f2019-03-04 11:11:33 +0000400 fileContent = t.read()
Lalit Magantidfe69ca2018-10-30 12:18:23 +0000401
Primiano Tucci711de1f2019-03-04 11:11:33 +0000402 file_desc_set_pb2 = descriptor_pb2.FileDescriptorSet()
403 file_desc_set_pb2.MergeFromString(fileContent)
Lalit Magantidfe69ca2018-10-30 12:18:23 +0000404
Primiano Tucci711de1f2019-03-04 11:11:33 +0000405 desc_by_path = {}
406 for f_desc_pb2 in file_desc_set_pb2.file:
407 f_desc_pb2_encode = f_desc_pb2.SerializeToString()
408 f_desc = descriptor.FileDescriptor(
409 name=f_desc_pb2.name,
410 package=f_desc_pb2.package,
411 serialized_pb=f_desc_pb2_encode)
Lalit Magantidfe69ca2018-10-30 12:18:23 +0000412
Primiano Tucci711de1f2019-03-04 11:11:33 +0000413 for desc in f_desc.message_types_by_name.values():
414 desc_by_path[desc.full_name] = desc
Lalit Magantidfe69ca2018-10-30 12:18:23 +0000415
Primiano Tucci711de1f2019-03-04 11:11:33 +0000416 trace = message_factory.MessageFactory().GetPrototype(
Ioannis Ilkos20d5e8b2019-05-16 15:43:26 +0100417 desc_by_path['perfetto.protos.Trace'])()
Primiano Tucci711de1f2019-03-04 11:11:33 +0000418 return Trace(trace)