• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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