1#!/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 21CLONE_THREAD = 0x00010000 22 23 24class Trace(object): 25 def __init__(self, trace): 26 self.trace = trace 27 self.proc_map = {} 28 self.proc_map[0] = "idle_thread" 29 30 def add_system_info(self, arch=None): 31 self.packet = self.trace.packet.add() 32 self.packet.system_info.utsname.machine = arch 33 34 def add_ftrace_packet(self, cpu): 35 self.packet = self.trace.packet.add() 36 self.packet.ftrace_events.cpu = cpu 37 38 def __add_ftrace_event(self, ts, tid): 39 ftrace = self.packet.ftrace_events.event.add() 40 ftrace.timestamp = ts 41 ftrace.pid = tid 42 return ftrace 43 44 def add_rss_stat(self, ts, tid, member, size): 45 ftrace = self.__add_ftrace_event(ts, tid) 46 rss_stat = ftrace.rss_stat 47 rss_stat.member = member 48 rss_stat.size = size 49 50 def add_oom_score_update(self, ts, oom_score_adj, pid): 51 ftrace = self.__add_ftrace_event(ts, pid) 52 oom_score = ftrace.oom_score_adj_update 53 oom_score.comm = self.proc_map[pid] 54 oom_score.oom_score_adj = oom_score_adj 55 oom_score.pid = pid 56 57 def add_sched(self, ts, prev_pid, next_pid, prev_comm=None, next_comm=None): 58 ftrace = self.__add_ftrace_event(ts, 0) 59 ss = ftrace.sched_switch 60 ss.prev_comm = prev_comm or self.proc_map[prev_pid] 61 ss.prev_pid = prev_pid 62 ss.next_pid = next_pid 63 ss.next_comm = next_comm or self.proc_map[next_pid] 64 65 def add_cpufreq(self, ts, freq, cpu): 66 ftrace = self.__add_ftrace_event(ts, 0) 67 cpufreq = ftrace.cpu_frequency 68 cpufreq.state = freq 69 cpufreq.cpu_id = cpu 70 71 def add_kernel_lmk(self, ts, tid): 72 ftrace = self.__add_ftrace_event(ts, tid) 73 lowmemory_kill = ftrace.lowmemory_kill 74 lowmemory_kill.pid = tid 75 76 def add_sys_enter(self, ts, tid, id): 77 ftrace = self.__add_ftrace_event(ts, tid) 78 sys_enter = ftrace.sys_enter 79 sys_enter.id = id 80 81 def add_sys_exit(self, ts, tid, id, ret): 82 ftrace = self.__add_ftrace_event(ts, tid) 83 sys_exit = ftrace.sys_exit 84 sys_exit.id = id 85 sys_exit.ret = ret 86 87 def add_newtask(self, ts, tid, new_tid, new_comm, flags): 88 ftrace = self.__add_ftrace_event(ts, tid) 89 newtask = ftrace.task_newtask 90 newtask.pid = new_tid 91 newtask.comm = new_comm 92 newtask.clone_flags = flags 93 94 def add_process_tree_packet(self, ts=None): 95 self.packet = self.trace.packet.add() 96 if ts is not None: 97 self.packet.timestamp = ts 98 99 def add_process(self, pid, ppid, cmdline): 100 process = self.packet.process_tree.processes.add() 101 process.pid = pid 102 process.ppid = ppid 103 process.cmdline.append(cmdline) 104 self.proc_map[pid] = cmdline 105 106 def add_thread(self, tid, tgid, cmdline): 107 thread = self.packet.process_tree.threads.add() 108 thread.tid = tid 109 thread.tgid = tgid 110 self.proc_map[tid] = cmdline 111 112 113def create_trace(): 114 parser = argparse.ArgumentParser() 115 parser.add_argument( 116 'trace_descriptor', type=str, help='location of trace descriptor') 117 args = parser.parse_args() 118 119 with open(args.trace_descriptor, "rb") as t: 120 fileContent = t.read() 121 122 file_desc_set_pb2 = descriptor_pb2.FileDescriptorSet() 123 file_desc_set_pb2.MergeFromString(fileContent) 124 125 desc_by_path = {} 126 for f_desc_pb2 in file_desc_set_pb2.file: 127 f_desc_pb2_encode = f_desc_pb2.SerializeToString() 128 f_desc = descriptor.FileDescriptor( 129 name=f_desc_pb2.name, 130 package=f_desc_pb2.package, 131 serialized_pb=f_desc_pb2_encode) 132 133 for desc in f_desc.message_types_by_name.values(): 134 desc_by_path[desc.full_name] = desc 135 136 trace = message_factory.MessageFactory().GetPrototype( 137 desc_by_path["perfetto.protos.Trace"])() 138 return Trace(trace) 139