1#!/usr/bin/env python3 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 collections import namedtuple 19from google.protobuf import descriptor, descriptor_pb2, message_factory, descriptor_pool 20 21CLONE_THREAD = 0x00010000 22CLONE_VFORK = 0x00004000 23CLONE_VM = 0x00000100 24 25 26def ms_to_ns(time_in_ms): 27 return int(time_in_ms * 1000000) 28 29 30def s_to_ns(time_in_s): 31 return int(time_in_s * 1000000000) 32 33 34class Trace(object): 35 36 def __init__(self, trace, prototypes): 37 self.trace = trace 38 self.prototypes = prototypes 39 self.proc_map = {} 40 self.proc_map[0] = 'idle_thread' 41 42 def add_system_info(self, arch="", fingerprint=""): 43 self.packet = self.trace.packet.add() 44 self.packet.system_info.utsname.machine = arch 45 self.packet.system_info.android_build_fingerprint = fingerprint 46 47 def add_ftrace_packet(self, cpu): 48 self.packet = self.trace.packet.add() 49 self.packet.ftrace_events.cpu = cpu 50 51 def add_packet(self, ts=None): 52 self.packet = self.trace.packet.add() 53 if ts is not None: 54 self.packet.timestamp = ts 55 return self.packet 56 57 def __add_ftrace_event(self, ts, tid): 58 ftrace = self.packet.ftrace_events.event.add() 59 ftrace.timestamp = ts 60 ftrace.pid = tid 61 return ftrace 62 63 def add_rss_stat(self, ts, tid, member, size, mm_id=None, curr=None): 64 ftrace = self.__add_ftrace_event(ts, tid) 65 rss_stat = ftrace.rss_stat 66 rss_stat.member = member 67 rss_stat.size = size 68 if mm_id is not None: 69 rss_stat.mm_id = mm_id 70 if curr is not None: 71 rss_stat.curr = curr 72 73 def add_ion_event(self, ts, tid, heap_name, len, size=0): 74 ftrace = self.__add_ftrace_event(ts, tid) 75 ion = ftrace.ion_heap_grow 76 ion.heap_name = heap_name 77 ion.len = len 78 ion.total_allocated = size 79 80 def add_oom_score_update(self, ts, oom_score_adj, pid): 81 ftrace = self.__add_ftrace_event(ts, pid) 82 oom_score = ftrace.oom_score_adj_update 83 oom_score.comm = self.proc_map[pid] 84 oom_score.oom_score_adj = oom_score_adj 85 oom_score.pid = pid 86 87 def add_sched(self, 88 ts, 89 prev_pid, 90 next_pid, 91 prev_comm=None, 92 next_comm=None, 93 prev_state=None): 94 ftrace = self.__add_ftrace_event(ts, 0) 95 ss = ftrace.sched_switch 96 ss.prev_comm = prev_comm or self.proc_map[prev_pid] 97 ss.prev_pid = prev_pid 98 ss.next_pid = next_pid 99 ss.next_comm = next_comm or self.proc_map[next_pid] 100 if prev_state: 101 if prev_state == 'R': 102 ss.prev_state = 0 103 elif prev_state == 'S': 104 ss.prev_state = 1 105 elif prev_state == 'U': 106 ss.prev_state = 2 107 else: 108 raise Exception('Invalid prev state {}'.format(prev_state)) 109 110 def add_cpufreq(self, ts, freq, cpu): 111 ftrace = self.__add_ftrace_event(ts, 0) 112 cpufreq = ftrace.cpu_frequency 113 cpufreq.state = freq 114 cpufreq.cpu_id = cpu 115 116 def add_kernel_lmk(self, ts, tid): 117 ftrace = self.__add_ftrace_event(ts, tid) 118 lowmemory_kill = ftrace.lowmemory_kill 119 lowmemory_kill.pid = tid 120 121 def add_sys_enter(self, ts, tid, id): 122 ftrace = self.__add_ftrace_event(ts, tid) 123 sys_enter = ftrace.sys_enter 124 sys_enter.id = id 125 126 def add_sys_exit(self, ts, tid, id, ret): 127 ftrace = self.__add_ftrace_event(ts, tid) 128 sys_exit = ftrace.sys_exit 129 sys_exit.id = id 130 sys_exit.ret = ret 131 132 def add_newtask(self, ts, tid, new_tid, new_comm, flags): 133 ftrace = self.__add_ftrace_event(ts, tid) 134 newtask = ftrace.task_newtask 135 newtask.pid = new_tid 136 newtask.comm = new_comm 137 newtask.clone_flags = flags 138 139 def add_process_free(self, ts, tid, comm, prio): 140 ftrace = self.__add_ftrace_event(ts, tid) 141 sched_process_free = ftrace.sched_process_free 142 sched_process_free.pid = tid 143 sched_process_free.comm = comm 144 sched_process_free.prio = prio 145 146 def add_rename(self, ts, tid, old_comm, new_comm, oom_score_adj): 147 ftrace = self.__add_ftrace_event(ts, tid) 148 task_rename = ftrace.task_rename 149 task_rename.pid = tid 150 task_rename.oldcomm = old_comm 151 task_rename.newcomm = new_comm 152 task_rename.oom_score_adj = oom_score_adj 153 154 def add_print(self, ts, tid, buf): 155 ftrace = self.__add_ftrace_event(ts, tid) 156 print_event = getattr(ftrace, 'print') 157 print_event.buf = buf 158 159 def add_kmalloc(self, ts, tid, bytes_alloc, bytes_req, call_site, gfp_flags, 160 ptr): 161 ftrace = self.__add_ftrace_event(ts, tid) 162 kmalloc = ftrace.kmalloc 163 kmalloc.bytes_alloc = bytes_alloc 164 kmalloc.bytes_req = bytes_req 165 kmalloc.call_site = call_site 166 kmalloc.gfp_flags = gfp_flags 167 kmalloc.ptr = ptr 168 169 def add_kfree(self, ts, tid, call_site, ptr): 170 ftrace = self.__add_ftrace_event(ts, tid) 171 kfree = ftrace.kfree 172 kfree.call_site = call_site 173 kfree.ptr = ptr 174 175 def add_atrace_counter(self, ts, pid, tid, buf, cnt): 176 self.add_print(ts, tid, 'C|{}|{}|{}'.format(pid, buf, cnt)) 177 178 def add_atrace_begin(self, ts, tid, pid, buf): 179 self.add_print(ts, tid, 'B|{}|{}'.format(pid, buf)) 180 181 def add_atrace_end(self, ts, tid, pid): 182 self.add_print(ts, tid, 'E|{}'.format(pid)) 183 184 def add_atrace_async_begin(self, ts, tid, pid, buf): 185 self.add_print(ts, tid, 'S|{}|{}|0'.format(pid, buf)) 186 187 def add_atrace_async_end(self, ts, tid, pid, buf): 188 self.add_print(ts, tid, 'F|{}|{}|0'.format(pid, buf)) 189 190 def add_process(self, pid, ppid, cmdline, uid=None): 191 process = self.packet.process_tree.processes.add() 192 process.pid = pid 193 process.ppid = ppid 194 process.cmdline.append(cmdline) 195 if uid is not None: 196 process.uid = uid 197 self.proc_map[pid] = cmdline 198 199 def add_thread(self, tid, tgid, cmdline, name=None): 200 thread = self.packet.process_tree.threads.add() 201 thread.tid = tid 202 thread.tgid = tgid 203 if name is not None: 204 thread.name = name 205 self.proc_map[tid] = cmdline 206 207 def add_battery_counters(self, ts, charge_uah, cap_prct, curr_ua, 208 curr_avg_ua): 209 self.packet = self.trace.packet.add() 210 self.packet.timestamp = ts 211 battery_count = self.packet.battery 212 battery_count.charge_counter_uah = charge_uah 213 battery_count.capacity_percent = cap_prct 214 battery_count.current_ua = curr_ua 215 battery_count.current_avg_ua = curr_avg_ua 216 217 def add_battery_counters_no_curr_ua(self, ts, charge_uah, cap_prct, 218 curr_avg_ua): 219 self.packet = self.trace.packet.add() 220 self.packet.timestamp = ts 221 battery_count = self.packet.battery 222 battery_count.charge_counter_uah = charge_uah 223 battery_count.capacity_percent = cap_prct 224 battery_count.current_avg_ua = curr_avg_ua 225 226 def add_power_rails_desc(self, index_val, name): 227 power_rails = self.packet.power_rails 228 descriptor = power_rails.rail_descriptor.add() 229 descriptor.index = index_val 230 descriptor.rail_name = name 231 232 def add_power_rails_data(self, ts, index_val, value): 233 power_rails = self.packet.power_rails 234 energy_data = power_rails.energy_data.add() 235 energy_data.index = index_val 236 energy_data.timestamp_ms = ts 237 energy_data.energy = value 238 239 def add_package_list(self, ts, name, uid, version_code): 240 packet = self.add_packet() 241 packet.timestamp = ts 242 plist = packet.packages_list 243 pinfo = plist.packages.add() 244 pinfo.name = name 245 pinfo.uid = uid 246 pinfo.version_code = version_code 247 248 def add_profile_packet(self, ts): 249 packet = self.add_packet() 250 packet.timestamp = ts 251 return packet.profile_packet 252 253 def add_clock_snapshot(self, clocks, seq_id=None): 254 packet = self.add_packet() 255 if seq_id is not None: 256 packet.trusted_packet_sequence_id = seq_id 257 snap = self.packet.clock_snapshot 258 for k, v in clocks.items(): 259 clock = snap.clocks.add() 260 clock.clock_id = k 261 clock.timestamp = v 262 263 def add_gpu_counter_spec(self, 264 ts, 265 counter_id, 266 name, 267 description=None, 268 unit_numerators=[], 269 unit_denominators=[]): 270 packet = self.add_packet() 271 packet.timestamp = ts 272 gpu_counters = packet.gpu_counter_event 273 counter_desc = gpu_counters.counter_descriptor 274 spec = counter_desc.specs.add() 275 spec.counter_id = counter_id 276 spec.name = name 277 if description is not None: 278 spec.description = description 279 spec.numerator_units.extend(unit_numerators) 280 spec.denominator_units.extend(unit_denominators) 281 282 def add_gpu_counter(self, ts, counter_id, value, clock_id=None, seq_id=None): 283 packet = self.add_packet() 284 packet.timestamp = ts 285 if clock_id is not None: 286 packet.timestamp_clock_id = clock_id 287 if seq_id is not None: 288 packet.trusted_packet_sequence_id = seq_id 289 gpu_counters = self.packet.gpu_counter_event 290 gpu_counter = gpu_counters.counters.add() 291 gpu_counter.counter_id = counter_id 292 gpu_counter.int_value = value 293 294 def add_gpu_render_stages_hw_queue_spec(self, specs=[]): 295 packet = self.add_packet() 296 spec = self.packet.gpu_render_stage_event.specifications 297 for s in specs: 298 hw_queue = spec.hw_queue.add() 299 hw_queue.name = s.get('name', '') 300 if 'description' in s: 301 hw_queue.description = s['description'] 302 303 def add_gpu_render_stages_stage_spec(self, specs=[]): 304 packet = self.add_packet() 305 spec = self.packet.gpu_render_stage_event.specifications 306 for s in specs: 307 stage = spec.stage.add() 308 stage.name = s.get('name', '') 309 if 'description' in s: 310 stage.description = s['description'] 311 312 def add_gpu_render_stages(self, 313 ts, 314 event_id, 315 duration, 316 hw_queue_id, 317 stage_id, 318 context, 319 render_target_handle=None, 320 render_pass_handle=None, 321 render_subpass_index_mask=None, 322 command_buffer_handle=None, 323 submission_id=None, 324 extra_data={}): 325 packet = self.add_packet() 326 packet.timestamp = ts 327 render_stage = self.packet.gpu_render_stage_event 328 render_stage.event_id = event_id 329 render_stage.duration = duration 330 render_stage.hw_queue_id = hw_queue_id 331 render_stage.stage_id = stage_id 332 render_stage.context = context 333 if render_target_handle is not None: 334 render_stage.render_target_handle = render_target_handle 335 if render_pass_handle is not None: 336 render_stage.render_pass_handle = render_pass_handle 337 if render_subpass_index_mask is not None: 338 for mask in render_subpass_index_mask: 339 render_stage.render_subpass_index_mask.append(mask) 340 if command_buffer_handle is not None: 341 render_stage.command_buffer_handle = command_buffer_handle 342 if submission_id is not None: 343 render_stage.submission_id = submission_id 344 for key, value in extra_data.items(): 345 data = render_stage.extra_data.add() 346 data.name = key 347 if value is not None: 348 data.value = value 349 350 def add_vk_debug_marker(self, ts, pid, vk_device, obj_type, obj, obj_name): 351 packet = self.add_packet() 352 packet.timestamp = ts 353 debug_marker = (self.packet.vulkan_api_event.vk_debug_utils_object_name) 354 debug_marker.pid = pid 355 debug_marker.vk_device = vk_device 356 debug_marker.object_type = obj_type 357 debug_marker.object = obj 358 debug_marker.object_name = obj_name 359 360 def add_vk_queue_submit(self, ts, dur, pid, tid, vk_queue, vk_command_buffers, 361 submission_id): 362 packet = self.add_packet() 363 packet.timestamp = ts 364 submit = (self.packet.vulkan_api_event.vk_queue_submit) 365 submit.duration_ns = dur 366 submit.pid = pid 367 submit.tid = tid 368 for cmd in vk_command_buffers: 369 submit.vk_command_buffers.append(cmd) 370 submit.submission_id = submission_id 371 372 def add_gpu_log(self, ts, severity, tag, message): 373 packet = self.add_packet() 374 packet.timestamp = ts 375 gpu_log = self.packet.gpu_log 376 gpu_log.severity = severity 377 gpu_log.tag = tag 378 gpu_log.log_message = message 379 380 def add_buffer_event_packet(self, ts, buffer_id, layer_name, frame_number, 381 event_type, duration): 382 packet = self.add_packet() 383 packet.timestamp = ts 384 buffer_event = packet.graphics_frame_event.buffer_event 385 if buffer_id >= 0: 386 buffer_event.buffer_id = buffer_id 387 buffer_event.layer_name = layer_name 388 buffer_event.frame_number = frame_number 389 if event_type >= 0: 390 buffer_event.type = event_type 391 buffer_event.duration_ns = duration 392 393 def add_cpu(self, freqs): 394 cpu = self.packet.cpu_info.cpus.add() 395 for freq in freqs: 396 cpu.frequencies.append(freq) 397 398 def add_process_stats(self, pid, freqs): 399 process = self.packet.process_stats.processes.add() 400 process.pid = pid 401 thread = process.threads.add() 402 thread.tid = pid * 10 403 for index in freqs: 404 thread.cpu_freq_indices.append(index) 405 thread.cpu_freq_ticks.append(freqs[index]) 406 407 def add_gpu_mem_total_ftrace_event(self, pid, ts, size): 408 ftrace = self.__add_ftrace_event(ts, pid) 409 gpu_mem_total_ftrace_event = ftrace.gpu_mem_total 410 gpu_mem_total_ftrace_event.pid = pid 411 gpu_mem_total_ftrace_event.size = size 412 413 def add_gpu_mem_total_event(self, pid, ts, size): 414 packet = self.add_packet() 415 packet.timestamp = ts 416 gpu_mem_total_event = packet.gpu_mem_total_event 417 gpu_mem_total_event.pid = pid 418 gpu_mem_total_event.size = size 419 420 def add_sched_blocked_reason(self, ts, pid, io_wait, unblock_pid): 421 ftrace = self.__add_ftrace_event(ts, unblock_pid) 422 sched_blocked_reason = ftrace.sched_blocked_reason 423 sched_blocked_reason.pid = pid 424 sched_blocked_reason.io_wait = io_wait 425 426 def add_track_event(self, 427 name=None, 428 ts=None, 429 track=None, 430 trusted_sequence_id=0, 431 cpu_time=None): 432 packet = self.add_packet(ts=ts) 433 if name is not None: 434 packet.track_event.name = name 435 if track is not None: 436 packet.track_event.track_uuid = track 437 packet.trusted_packet_sequence_id = trusted_sequence_id 438 if cpu_time is not None: 439 packet.track_event.extra_counter_values.append(cpu_time) 440 return packet 441 442 def add_track_descriptor(self, uuid, parent=None): 443 packet = self.add_packet() 444 track_descriptor = packet.track_descriptor 445 if uuid is not None: 446 track_descriptor.uuid = uuid 447 if parent is not None: 448 track_descriptor.parent_uuid = parent 449 return packet 450 451 def add_process_track_descriptor(self, process_track, pid=None): 452 packet = self.add_track_descriptor(process_track) 453 packet.track_descriptor.process.pid = pid 454 return packet 455 456 def add_chrome_process_track_descriptor( 457 self, 458 process_track, 459 pid=None, 460 process_type=None, 461 host_app_package_name="org.chromium.chrome"): 462 if process_type is None: 463 process_type = self.prototypes.ChromeProcessDescriptor \ 464 .ProcessType \ 465 .PROCESS_RENDERER 466 467 packet = self.add_process_track_descriptor(process_track, pid=pid) 468 chrome_process = packet.track_descriptor.chrome_process 469 chrome_process.process_type = process_type 470 chrome_process.host_app_package_name = host_app_package_name 471 return packet 472 473 def add_thread_track_descriptor(self, 474 process_track, 475 thread_track, 476 trusted_packet_sequence_id=None, 477 pid=None, 478 tid=None): 479 packet = self.add_track_descriptor(thread_track, parent=process_track) 480 packet.trusted_packet_sequence_id = trusted_packet_sequence_id 481 packet.track_descriptor.thread.pid = pid 482 packet.track_descriptor.thread.tid = tid 483 return packet 484 485 def add_chrome_thread_track_descriptor(self, 486 process_track, 487 thread_track, 488 trusted_packet_sequence_id=None, 489 pid=None, 490 tid=None, 491 thread_type=None): 492 if thread_type is None: 493 thread_type = self.prototypes.ThreadDescriptor \ 494 .ChromeThreadType \ 495 .CHROME_THREAD_TYPE_UNSPECIFIED 496 497 packet = self.add_thread_track_descriptor( 498 process_track, 499 thread_track, 500 trusted_packet_sequence_id=trusted_packet_sequence_id, 501 pid=pid, 502 tid=tid) 503 packet.track_descriptor.thread.chrome_thread_type = thread_type 504 return packet 505 506 def add_trace_packet_defaults(self, 507 trusted_packet_sequence_id=None, 508 thread_track=None, 509 counter_track=None): 510 packet = self.add_track_descriptor(None) 511 packet.trusted_packet_sequence_id = trusted_packet_sequence_id 512 track_event_defaults = packet.trace_packet_defaults.track_event_defaults 513 track_event_defaults.track_uuid = thread_track 514 track_event_defaults.extra_counter_track_uuids.append(counter_track) 515 return packet 516 517 def add_counter_track_descriptor(self, 518 trusted_packet_sequence_id=None, 519 thread_track=None, 520 counter_track=None): 521 packet = self.add_track_descriptor(counter_track, parent=thread_track) 522 packet.trusted_packet_sequence_id = trusted_packet_sequence_id 523 packet.track_descriptor.counter.type = self.prototypes.CounterDescriptor \ 524 .BuiltinCounterType \ 525 .COUNTER_THREAD_TIME_NS 526 return packet 527 528 def add_chrome_thread_with_cpu_counter(self, 529 process_track, 530 thread_track, 531 trusted_packet_sequence_id=None, 532 counter_track=None, 533 pid=None, 534 tid=None, 535 thread_type=None): 536 self.add_chrome_thread_track_descriptor( 537 process_track, 538 thread_track, 539 trusted_packet_sequence_id=trusted_packet_sequence_id, 540 pid=pid, 541 tid=tid, 542 thread_type=thread_type) 543 self.add_trace_packet_defaults( 544 trusted_packet_sequence_id=trusted_packet_sequence_id, 545 counter_track=counter_track, 546 thread_track=thread_track) 547 548 self.add_counter_track_descriptor( 549 trusted_packet_sequence_id=trusted_packet_sequence_id, 550 counter_track=counter_track, 551 thread_track=thread_track) 552 553 def add_track_event_slice_begin(self, 554 name, 555 ts, 556 track=None, 557 trusted_sequence_id=0, 558 cpu_time=None): 559 packet = self.add_track_event( 560 name, 561 ts=ts, 562 track=track, 563 trusted_sequence_id=trusted_sequence_id, 564 cpu_time=cpu_time) 565 packet.track_event.type = self.prototypes.TrackEvent.Type.TYPE_SLICE_BEGIN 566 return packet 567 568 def add_track_event_slice_end(self, 569 ts, 570 track=None, 571 trusted_sequence_id=0, 572 cpu_time=None): 573 packet = self.add_track_event( 574 ts=ts, 575 track=track, 576 trusted_sequence_id=trusted_sequence_id, 577 cpu_time=cpu_time) 578 packet.track_event.type = self.prototypes.TrackEvent.Type.TYPE_SLICE_END 579 return packet 580 581 # Returns the start slice packet. 582 def add_track_event_slice(self, 583 name, 584 ts, 585 dur, 586 track=None, 587 trusted_sequence_id=0, 588 cpu_start=None, 589 cpu_delta=None): 590 591 packet = self.add_track_event_slice_begin( 592 name, 593 ts, 594 track=track, 595 trusted_sequence_id=trusted_sequence_id, 596 cpu_time=cpu_start) 597 598 if dur >= 0: 599 cpu_end = cpu_start + cpu_delta if cpu_start is not None else None 600 self.add_track_event_slice_end( 601 ts + dur, 602 track=track, 603 trusted_sequence_id=trusted_sequence_id, 604 cpu_time=cpu_end) 605 606 return packet 607 608 def add_rail_mode_slice(self, ts, dur, track, mode): 609 packet = self.add_track_event_slice( 610 "Scheduler.RAILMode", ts=ts, dur=dur, track=track) 611 packet.track_event.chrome_renderer_scheduler_state.rail_mode = mode 612 613 def add_latency_info_flow(self, 614 ts, 615 dur, 616 track=None, 617 trusted_sequence_id=None, 618 trace_id=None, 619 flow_ids=[], 620 terminating_flow_ids=[]): 621 packet = self.add_track_event_slice( 622 "LatencyInfo.Flow", 623 ts, 624 dur, 625 track=track, 626 trusted_sequence_id=trusted_sequence_id) 627 if trace_id is not None: 628 packet.track_event.chrome_latency_info.trace_id = trace_id 629 for flow_id in flow_ids: 630 packet.track_event.flow_ids.append(flow_id) 631 for flow_id in terminating_flow_ids: 632 packet.track_event.terminating_flow_ids.append(flow_id) 633 return packet 634 635 def add_input_latency_event_slice(self, 636 name, 637 ts, 638 dur, 639 track=None, 640 trace_id=None, 641 gesture_scroll_id=None, 642 is_coalesced=None): 643 packet = self.add_track_event_slice( 644 "InputLatency::" + name, ts=ts, dur=dur, track=track) 645 packet.track_event.chrome_latency_info.trace_id = trace_id 646 packet.track_event.chrome_latency_info.gesture_scroll_id = gesture_scroll_id 647 if is_coalesced is not None: 648 packet.track_event.chrome_latency_info.is_coalesced = is_coalesced 649 return packet 650 651 def add_chrome_metadata(self, os_name=None): 652 metadata = self.add_packet().chrome_events.metadata.add() 653 if os_name is not None: 654 metadata.name = "os-name" 655 metadata.string_value = os_name 656 657 return metadata 658 659 def add_expected_display_frame_start_event(self, ts, cookie, token, pid): 660 packet = self.add_packet() 661 packet.timestamp = ts 662 event = packet.frame_timeline_event.expected_display_frame_start 663 if token != -1: 664 event.cookie = cookie 665 event.token = token 666 event.pid = pid 667 668 def add_actual_display_frame_start_event(self, ts, cookie, token, pid, 669 present_type, on_time_finish, 670 gpu_composition, jank_type, prediction_type): 671 packet = self.add_packet() 672 packet.timestamp = ts 673 event = packet.frame_timeline_event.actual_display_frame_start 674 if token != -1: 675 event.cookie = cookie 676 event.token = token 677 event.pid = pid 678 event.present_type = present_type 679 event.on_time_finish = on_time_finish 680 event.gpu_composition = gpu_composition 681 event.jank_type = jank_type 682 event.prediction_type = prediction_type 683 684 def add_expected_surface_frame_start_event(self, ts, cookie, token, 685 display_frame_token, pid, 686 layer_name): 687 packet = self.add_packet() 688 packet.timestamp = ts 689 event = packet.frame_timeline_event.expected_surface_frame_start 690 if token != -1 and display_frame_token != -1: 691 event.cookie = cookie 692 event.token = token 693 event.display_frame_token = display_frame_token 694 event.pid = pid 695 event.layer_name = layer_name 696 697 def add_actual_surface_frame_start_event(self, ts, cookie, token, 698 display_frame_token, pid, layer_name, 699 present_type, on_time_finish, 700 gpu_composition, jank_type, prediction_type): 701 packet = self.add_packet() 702 packet.timestamp = ts 703 event = packet.frame_timeline_event.actual_surface_frame_start 704 if token != -1 and display_frame_token != -1: 705 event.cookie = cookie 706 event.token = token 707 event.display_frame_token = display_frame_token 708 event.pid = pid 709 event.layer_name = layer_name 710 event.present_type = present_type 711 event.on_time_finish = on_time_finish 712 event.gpu_composition = gpu_composition 713 event.jank_type = jank_type 714 event.prediction_type = prediction_type 715 716 def add_frame_end_event(self, ts, cookie): 717 packet = self.add_packet() 718 packet.timestamp = ts 719 event = packet.frame_timeline_event.frame_end 720 event.cookie = cookie 721 722 723def read_descriptor(file_name): 724 with open(file_name, 'rb') as f: 725 contents = f.read() 726 727 descriptor = descriptor_pb2.FileDescriptorSet() 728 descriptor.MergeFromString(contents) 729 730 return descriptor 731 732 733def create_pool(args): 734 trace_descriptor = read_descriptor(args.trace_descriptor) 735 736 pool = descriptor_pool.DescriptorPool() 737 for file in trace_descriptor.file: 738 pool.Add(file) 739 740 return pool 741 742 743def create_trace(): 744 parser = argparse.ArgumentParser() 745 parser.add_argument( 746 'trace_descriptor', type=str, help='location of trace descriptor') 747 args = parser.parse_args() 748 749 pool = create_pool(args) 750 factory = message_factory.MessageFactory(pool) 751 ProtoTrace = factory.GetPrototype( 752 pool.FindMessageTypeByName('perfetto.protos.Trace')) 753 754 class EnumPrototype(object): 755 756 def from_descriptor(desc): 757 res = EnumPrototype() 758 for desc in desc.values: 759 setattr(res, desc.name, desc.number) 760 return res 761 762 Prototypes = namedtuple('Prototypes', [ 763 'TrackEvent', 764 'ChromeRAILMode', 765 'ThreadDescriptor', 766 'ChromeProcessDescriptor', 767 'CounterDescriptor', 768 ]) 769 prototypes = Prototypes( 770 TrackEvent=factory.GetPrototype( 771 pool.FindMessageTypeByName('perfetto.protos.TrackEvent')), 772 ChromeRAILMode=EnumPrototype.from_descriptor( 773 pool.FindEnumTypeByName('perfetto.protos.ChromeRAILMode')), 774 ThreadDescriptor=factory.GetPrototype( 775 pool.FindMessageTypeByName('perfetto.protos.ThreadDescriptor')), 776 ChromeProcessDescriptor=factory.GetPrototype( 777 pool.FindMessageTypeByName( 778 'perfetto.protos.ChromeProcessDescriptor')), 779 CounterDescriptor=factory.GetPrototype( 780 pool.FindMessageTypeByName('perfetto.protos.CounterDescriptor')), 781 ) 782 return Trace(ProtoTrace(), prototypes) 783