xref: /aosp_15_r20/system/extras/simpleperf/scripts/report.py (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1*288bf522SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*288bf522SAndroid Build Coastguard Worker#
3*288bf522SAndroid Build Coastguard Worker# Copyright (C) 2015 The Android Open Source Project
4*288bf522SAndroid Build Coastguard Worker#
5*288bf522SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*288bf522SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*288bf522SAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*288bf522SAndroid Build Coastguard Worker#
9*288bf522SAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
10*288bf522SAndroid Build Coastguard Worker#
11*288bf522SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*288bf522SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*288bf522SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*288bf522SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*288bf522SAndroid Build Coastguard Worker# limitations under the License.
16*288bf522SAndroid Build Coastguard Worker#
17*288bf522SAndroid Build Coastguard Worker
18*288bf522SAndroid Build Coastguard Worker"""Simpleperf gui reporter: provide gui interface for simpleperf report command.
19*288bf522SAndroid Build Coastguard Worker
20*288bf522SAndroid Build Coastguard WorkerThere are two ways to use gui reporter. One way is to pass it a report file
21*288bf522SAndroid Build Coastguard Workergenerated by simpleperf report command, and reporter will display it. The
22*288bf522SAndroid Build Coastguard Workerother ways is to pass it any arguments you want to use when calling
23*288bf522SAndroid Build Coastguard Workersimpleperf report command. The reporter will call `simpleperf report` to
24*288bf522SAndroid Build Coastguard Workergenerate report file, and display it.
25*288bf522SAndroid Build Coastguard Worker"""
26*288bf522SAndroid Build Coastguard Worker
27*288bf522SAndroid Build Coastguard Workerimport logging
28*288bf522SAndroid Build Coastguard Workerimport os
29*288bf522SAndroid Build Coastguard Workerimport os.path
30*288bf522SAndroid Build Coastguard Workerimport re
31*288bf522SAndroid Build Coastguard Workerimport subprocess
32*288bf522SAndroid Build Coastguard Workerimport sys
33*288bf522SAndroid Build Coastguard Worker
34*288bf522SAndroid Build Coastguard Workertry:
35*288bf522SAndroid Build Coastguard Worker    from tkinter import *
36*288bf522SAndroid Build Coastguard Worker    from tkinter.font import Font
37*288bf522SAndroid Build Coastguard Worker    from tkinter.ttk import *
38*288bf522SAndroid Build Coastguard Workerexcept ImportError:
39*288bf522SAndroid Build Coastguard Worker    from Tkinter import *
40*288bf522SAndroid Build Coastguard Worker    from tkFont import Font
41*288bf522SAndroid Build Coastguard Worker    from ttk import *
42*288bf522SAndroid Build Coastguard Worker
43*288bf522SAndroid Build Coastguard Workerfrom simpleperf_utils import *
44*288bf522SAndroid Build Coastguard Worker
45*288bf522SAndroid Build Coastguard WorkerPAD_X = 3
46*288bf522SAndroid Build Coastguard WorkerPAD_Y = 3
47*288bf522SAndroid Build Coastguard Worker
48*288bf522SAndroid Build Coastguard Worker
49*288bf522SAndroid Build Coastguard Workerclass CallTreeNode(object):
50*288bf522SAndroid Build Coastguard Worker
51*288bf522SAndroid Build Coastguard Worker    """Representing a node in call-graph."""
52*288bf522SAndroid Build Coastguard Worker
53*288bf522SAndroid Build Coastguard Worker    def __init__(self, percentage, function_name):
54*288bf522SAndroid Build Coastguard Worker        self.percentage = percentage
55*288bf522SAndroid Build Coastguard Worker        self.call_stack = [function_name]
56*288bf522SAndroid Build Coastguard Worker        self.children = []
57*288bf522SAndroid Build Coastguard Worker
58*288bf522SAndroid Build Coastguard Worker    def add_call(self, function_name):
59*288bf522SAndroid Build Coastguard Worker        self.call_stack.append(function_name)
60*288bf522SAndroid Build Coastguard Worker
61*288bf522SAndroid Build Coastguard Worker    def add_child(self, node):
62*288bf522SAndroid Build Coastguard Worker        self.children.append(node)
63*288bf522SAndroid Build Coastguard Worker
64*288bf522SAndroid Build Coastguard Worker    def __str__(self):
65*288bf522SAndroid Build Coastguard Worker        strs = self.dump()
66*288bf522SAndroid Build Coastguard Worker        return '\n'.join(strs)
67*288bf522SAndroid Build Coastguard Worker
68*288bf522SAndroid Build Coastguard Worker    def dump(self):
69*288bf522SAndroid Build Coastguard Worker        strs = []
70*288bf522SAndroid Build Coastguard Worker        strs.append('CallTreeNode percentage = %.2f' % self.percentage)
71*288bf522SAndroid Build Coastguard Worker        for function_name in self.call_stack:
72*288bf522SAndroid Build Coastguard Worker            strs.append(' %s' % function_name)
73*288bf522SAndroid Build Coastguard Worker        for child in self.children:
74*288bf522SAndroid Build Coastguard Worker            child_strs = child.dump()
75*288bf522SAndroid Build Coastguard Worker            strs.extend(['  ' + x for x in child_strs])
76*288bf522SAndroid Build Coastguard Worker        return strs
77*288bf522SAndroid Build Coastguard Worker
78*288bf522SAndroid Build Coastguard Worker
79*288bf522SAndroid Build Coastguard Workerclass ReportItem(object):
80*288bf522SAndroid Build Coastguard Worker
81*288bf522SAndroid Build Coastguard Worker    """Representing one item in report, may contain a CallTree."""
82*288bf522SAndroid Build Coastguard Worker
83*288bf522SAndroid Build Coastguard Worker    def __init__(self, raw_line):
84*288bf522SAndroid Build Coastguard Worker        self.raw_line = raw_line
85*288bf522SAndroid Build Coastguard Worker        self.call_tree = None
86*288bf522SAndroid Build Coastguard Worker
87*288bf522SAndroid Build Coastguard Worker    def __str__(self):
88*288bf522SAndroid Build Coastguard Worker        strs = []
89*288bf522SAndroid Build Coastguard Worker        strs.append('ReportItem (raw_line %s)' % self.raw_line)
90*288bf522SAndroid Build Coastguard Worker        if self.call_tree is not None:
91*288bf522SAndroid Build Coastguard Worker            strs.append('%s' % self.call_tree)
92*288bf522SAndroid Build Coastguard Worker        return '\n'.join(strs)
93*288bf522SAndroid Build Coastguard Worker
94*288bf522SAndroid Build Coastguard Worker
95*288bf522SAndroid Build Coastguard Workerclass EventReport(object):
96*288bf522SAndroid Build Coastguard Worker
97*288bf522SAndroid Build Coastguard Worker    """Representing report for one event attr."""
98*288bf522SAndroid Build Coastguard Worker
99*288bf522SAndroid Build Coastguard Worker    def __init__(self, common_report_context):
100*288bf522SAndroid Build Coastguard Worker        self.context = common_report_context[:]
101*288bf522SAndroid Build Coastguard Worker        self.title_line = None
102*288bf522SAndroid Build Coastguard Worker        self.report_items = []
103*288bf522SAndroid Build Coastguard Worker
104*288bf522SAndroid Build Coastguard Worker
105*288bf522SAndroid Build Coastguard Workerdef parse_event_reports(lines):
106*288bf522SAndroid Build Coastguard Worker    # Parse common report context
107*288bf522SAndroid Build Coastguard Worker    common_report_context = []
108*288bf522SAndroid Build Coastguard Worker    line_id = 0
109*288bf522SAndroid Build Coastguard Worker    while line_id < len(lines):
110*288bf522SAndroid Build Coastguard Worker        line = lines[line_id]
111*288bf522SAndroid Build Coastguard Worker        if not line or line.find('Event:') == 0:
112*288bf522SAndroid Build Coastguard Worker            break
113*288bf522SAndroid Build Coastguard Worker        common_report_context.append(line)
114*288bf522SAndroid Build Coastguard Worker        line_id += 1
115*288bf522SAndroid Build Coastguard Worker
116*288bf522SAndroid Build Coastguard Worker    event_reports = []
117*288bf522SAndroid Build Coastguard Worker    in_report_context = True
118*288bf522SAndroid Build Coastguard Worker    cur_event_report = EventReport(common_report_context)
119*288bf522SAndroid Build Coastguard Worker    cur_report_item = None
120*288bf522SAndroid Build Coastguard Worker    call_tree_stack = {}
121*288bf522SAndroid Build Coastguard Worker    vertical_columns = []
122*288bf522SAndroid Build Coastguard Worker    last_node = None
123*288bf522SAndroid Build Coastguard Worker
124*288bf522SAndroid Build Coastguard Worker    has_skipped_callgraph = False
125*288bf522SAndroid Build Coastguard Worker
126*288bf522SAndroid Build Coastguard Worker    for line in lines[line_id:]:
127*288bf522SAndroid Build Coastguard Worker        if not line:
128*288bf522SAndroid Build Coastguard Worker            in_report_context = not in_report_context
129*288bf522SAndroid Build Coastguard Worker            if in_report_context:
130*288bf522SAndroid Build Coastguard Worker                cur_event_report = EventReport(common_report_context)
131*288bf522SAndroid Build Coastguard Worker            continue
132*288bf522SAndroid Build Coastguard Worker
133*288bf522SAndroid Build Coastguard Worker        if in_report_context:
134*288bf522SAndroid Build Coastguard Worker            cur_event_report.context.append(line)
135*288bf522SAndroid Build Coastguard Worker            if line.find('Event:') == 0:
136*288bf522SAndroid Build Coastguard Worker                event_reports.append(cur_event_report)
137*288bf522SAndroid Build Coastguard Worker            continue
138*288bf522SAndroid Build Coastguard Worker
139*288bf522SAndroid Build Coastguard Worker        if cur_event_report.title_line is None:
140*288bf522SAndroid Build Coastguard Worker            cur_event_report.title_line = line
141*288bf522SAndroid Build Coastguard Worker        elif not line[0].isspace():
142*288bf522SAndroid Build Coastguard Worker            cur_report_item = ReportItem(line)
143*288bf522SAndroid Build Coastguard Worker            cur_event_report.report_items.append(cur_report_item)
144*288bf522SAndroid Build Coastguard Worker            # Each report item can have different column depths.
145*288bf522SAndroid Build Coastguard Worker            vertical_columns = []
146*288bf522SAndroid Build Coastguard Worker        else:
147*288bf522SAndroid Build Coastguard Worker            for i in range(len(line)):
148*288bf522SAndroid Build Coastguard Worker                if line[i] == '|':
149*288bf522SAndroid Build Coastguard Worker                    if not vertical_columns or vertical_columns[-1] < i:
150*288bf522SAndroid Build Coastguard Worker                        vertical_columns.append(i)
151*288bf522SAndroid Build Coastguard Worker
152*288bf522SAndroid Build Coastguard Worker            if not line.strip('| \t'):
153*288bf522SAndroid Build Coastguard Worker                continue
154*288bf522SAndroid Build Coastguard Worker            if 'skipped in brief callgraph mode' in line:
155*288bf522SAndroid Build Coastguard Worker                has_skipped_callgraph = True
156*288bf522SAndroid Build Coastguard Worker                continue
157*288bf522SAndroid Build Coastguard Worker
158*288bf522SAndroid Build Coastguard Worker            if line.find('-') == -1:
159*288bf522SAndroid Build Coastguard Worker                line = line.strip('| \t')
160*288bf522SAndroid Build Coastguard Worker                function_name = line
161*288bf522SAndroid Build Coastguard Worker                last_node.add_call(function_name)
162*288bf522SAndroid Build Coastguard Worker            else:
163*288bf522SAndroid Build Coastguard Worker                pos = line.find('-')
164*288bf522SAndroid Build Coastguard Worker                depth = -1
165*288bf522SAndroid Build Coastguard Worker                for i in range(len(vertical_columns)):
166*288bf522SAndroid Build Coastguard Worker                    if pos >= vertical_columns[i]:
167*288bf522SAndroid Build Coastguard Worker                        depth = i
168*288bf522SAndroid Build Coastguard Worker                assert depth != -1
169*288bf522SAndroid Build Coastguard Worker
170*288bf522SAndroid Build Coastguard Worker                line = line.strip('|- \t')
171*288bf522SAndroid Build Coastguard Worker                m = re.search(r'^([\d\.]+)%[-\s]+(.+)$', line)
172*288bf522SAndroid Build Coastguard Worker                if m:
173*288bf522SAndroid Build Coastguard Worker                    percentage = float(m.group(1))
174*288bf522SAndroid Build Coastguard Worker                    function_name = m.group(2)
175*288bf522SAndroid Build Coastguard Worker                else:
176*288bf522SAndroid Build Coastguard Worker                    percentage = 100.0
177*288bf522SAndroid Build Coastguard Worker                    function_name = line
178*288bf522SAndroid Build Coastguard Worker
179*288bf522SAndroid Build Coastguard Worker                node = CallTreeNode(percentage, function_name)
180*288bf522SAndroid Build Coastguard Worker                if depth == 0:
181*288bf522SAndroid Build Coastguard Worker                    cur_report_item.call_tree = node
182*288bf522SAndroid Build Coastguard Worker                else:
183*288bf522SAndroid Build Coastguard Worker                    call_tree_stack[depth - 1].add_child(node)
184*288bf522SAndroid Build Coastguard Worker                call_tree_stack[depth] = node
185*288bf522SAndroid Build Coastguard Worker                last_node = node
186*288bf522SAndroid Build Coastguard Worker
187*288bf522SAndroid Build Coastguard Worker    if has_skipped_callgraph:
188*288bf522SAndroid Build Coastguard Worker        logging.warning('some callgraphs are skipped in brief callgraph mode')
189*288bf522SAndroid Build Coastguard Worker
190*288bf522SAndroid Build Coastguard Worker    return event_reports
191*288bf522SAndroid Build Coastguard Worker
192*288bf522SAndroid Build Coastguard Worker
193*288bf522SAndroid Build Coastguard Workerclass ReportWindow(object):
194*288bf522SAndroid Build Coastguard Worker
195*288bf522SAndroid Build Coastguard Worker    """A window used to display report file."""
196*288bf522SAndroid Build Coastguard Worker
197*288bf522SAndroid Build Coastguard Worker    def __init__(self, main, report_context, title_line, report_items):
198*288bf522SAndroid Build Coastguard Worker        frame = Frame(main)
199*288bf522SAndroid Build Coastguard Worker        frame.pack(fill=BOTH, expand=1)
200*288bf522SAndroid Build Coastguard Worker
201*288bf522SAndroid Build Coastguard Worker        font = Font(family='courier', size=12)
202*288bf522SAndroid Build Coastguard Worker
203*288bf522SAndroid Build Coastguard Worker        # Report Context
204*288bf522SAndroid Build Coastguard Worker        for line in report_context:
205*288bf522SAndroid Build Coastguard Worker            label = Label(frame, text=line, font=font)
206*288bf522SAndroid Build Coastguard Worker            label.pack(anchor=W, padx=PAD_X, pady=PAD_Y)
207*288bf522SAndroid Build Coastguard Worker
208*288bf522SAndroid Build Coastguard Worker        # Space
209*288bf522SAndroid Build Coastguard Worker        label = Label(frame, text='', font=font)
210*288bf522SAndroid Build Coastguard Worker        label.pack(anchor=W, padx=PAD_X, pady=PAD_Y)
211*288bf522SAndroid Build Coastguard Worker
212*288bf522SAndroid Build Coastguard Worker        # Title
213*288bf522SAndroid Build Coastguard Worker        label = Label(frame, text='  ' + title_line, font=font)
214*288bf522SAndroid Build Coastguard Worker        label.pack(anchor=W, padx=PAD_X, pady=PAD_Y)
215*288bf522SAndroid Build Coastguard Worker
216*288bf522SAndroid Build Coastguard Worker        # Report Items
217*288bf522SAndroid Build Coastguard Worker        report_frame = Frame(frame)
218*288bf522SAndroid Build Coastguard Worker        report_frame.pack(fill=BOTH, expand=1)
219*288bf522SAndroid Build Coastguard Worker
220*288bf522SAndroid Build Coastguard Worker        yscrollbar = Scrollbar(report_frame)
221*288bf522SAndroid Build Coastguard Worker        yscrollbar.pack(side=RIGHT, fill=Y)
222*288bf522SAndroid Build Coastguard Worker        xscrollbar = Scrollbar(report_frame, orient=HORIZONTAL)
223*288bf522SAndroid Build Coastguard Worker        xscrollbar.pack(side=BOTTOM, fill=X)
224*288bf522SAndroid Build Coastguard Worker
225*288bf522SAndroid Build Coastguard Worker        tree = Treeview(report_frame, columns=[title_line], show='')
226*288bf522SAndroid Build Coastguard Worker        tree.pack(side=LEFT, fill=BOTH, expand=1)
227*288bf522SAndroid Build Coastguard Worker        tree.tag_configure('set_font', font=font)
228*288bf522SAndroid Build Coastguard Worker
229*288bf522SAndroid Build Coastguard Worker        tree.config(yscrollcommand=yscrollbar.set)
230*288bf522SAndroid Build Coastguard Worker        yscrollbar.config(command=tree.yview)
231*288bf522SAndroid Build Coastguard Worker        tree.config(xscrollcommand=xscrollbar.set)
232*288bf522SAndroid Build Coastguard Worker        xscrollbar.config(command=tree.xview)
233*288bf522SAndroid Build Coastguard Worker
234*288bf522SAndroid Build Coastguard Worker        self.display_report_items(tree, report_items)
235*288bf522SAndroid Build Coastguard Worker
236*288bf522SAndroid Build Coastguard Worker    def display_report_items(self, tree, report_items):
237*288bf522SAndroid Build Coastguard Worker        for report_item in report_items:
238*288bf522SAndroid Build Coastguard Worker            prefix_str = '+ ' if report_item.call_tree is not None else '  '
239*288bf522SAndroid Build Coastguard Worker            id = tree.insert(
240*288bf522SAndroid Build Coastguard Worker                '',
241*288bf522SAndroid Build Coastguard Worker                'end',
242*288bf522SAndroid Build Coastguard Worker                None,
243*288bf522SAndroid Build Coastguard Worker                values=[
244*288bf522SAndroid Build Coastguard Worker                    prefix_str +
245*288bf522SAndroid Build Coastguard Worker                    report_item.raw_line],
246*288bf522SAndroid Build Coastguard Worker                tag='set_font')
247*288bf522SAndroid Build Coastguard Worker            if report_item.call_tree is not None:
248*288bf522SAndroid Build Coastguard Worker                self.display_call_tree(tree, id, report_item.call_tree, 1)
249*288bf522SAndroid Build Coastguard Worker
250*288bf522SAndroid Build Coastguard Worker    def display_call_tree(self, tree, parent_id, node, indent):
251*288bf522SAndroid Build Coastguard Worker        id = parent_id
252*288bf522SAndroid Build Coastguard Worker        indent_str = '    ' * indent
253*288bf522SAndroid Build Coastguard Worker
254*288bf522SAndroid Build Coastguard Worker        if node.percentage != 100.0:
255*288bf522SAndroid Build Coastguard Worker            percentage_str = '%.2f%% ' % node.percentage
256*288bf522SAndroid Build Coastguard Worker        else:
257*288bf522SAndroid Build Coastguard Worker            percentage_str = ''
258*288bf522SAndroid Build Coastguard Worker
259*288bf522SAndroid Build Coastguard Worker        for i in range(len(node.call_stack)):
260*288bf522SAndroid Build Coastguard Worker            s = indent_str
261*288bf522SAndroid Build Coastguard Worker            s += '+ ' if node.children and i == len(node.call_stack) - 1 else '  '
262*288bf522SAndroid Build Coastguard Worker            s += percentage_str if i == 0 else ' ' * len(percentage_str)
263*288bf522SAndroid Build Coastguard Worker            s += node.call_stack[i]
264*288bf522SAndroid Build Coastguard Worker            child_open = False if i == len(node.call_stack) - 1 and indent > 1 else True
265*288bf522SAndroid Build Coastguard Worker            id = tree.insert(id, 'end', None, values=[s], open=child_open,
266*288bf522SAndroid Build Coastguard Worker                             tag='set_font')
267*288bf522SAndroid Build Coastguard Worker
268*288bf522SAndroid Build Coastguard Worker        for child in node.children:
269*288bf522SAndroid Build Coastguard Worker            self.display_call_tree(tree, id, child, indent + 1)
270*288bf522SAndroid Build Coastguard Worker
271*288bf522SAndroid Build Coastguard Worker
272*288bf522SAndroid Build Coastguard Workerdef display_report_file(report_file, self_kill_after_sec):
273*288bf522SAndroid Build Coastguard Worker    fh = open(report_file, 'r')
274*288bf522SAndroid Build Coastguard Worker    lines = fh.readlines()
275*288bf522SAndroid Build Coastguard Worker    fh.close()
276*288bf522SAndroid Build Coastguard Worker
277*288bf522SAndroid Build Coastguard Worker    lines = [x.rstrip() for x in lines]
278*288bf522SAndroid Build Coastguard Worker    event_reports = parse_event_reports(lines)
279*288bf522SAndroid Build Coastguard Worker
280*288bf522SAndroid Build Coastguard Worker    if event_reports:
281*288bf522SAndroid Build Coastguard Worker        root = Tk()
282*288bf522SAndroid Build Coastguard Worker        for i in range(len(event_reports)):
283*288bf522SAndroid Build Coastguard Worker            report = event_reports[i]
284*288bf522SAndroid Build Coastguard Worker            parent = root if i == 0 else Toplevel(root)
285*288bf522SAndroid Build Coastguard Worker            ReportWindow(parent, report.context, report.title_line, report.report_items)
286*288bf522SAndroid Build Coastguard Worker        if self_kill_after_sec:
287*288bf522SAndroid Build Coastguard Worker            root.after(self_kill_after_sec * 1000, lambda: root.destroy())
288*288bf522SAndroid Build Coastguard Worker        root.mainloop()
289*288bf522SAndroid Build Coastguard Worker
290*288bf522SAndroid Build Coastguard Worker
291*288bf522SAndroid Build Coastguard Workerdef call_simpleperf_report(args, show_gui, self_kill_after_sec):
292*288bf522SAndroid Build Coastguard Worker    simpleperf_path = get_host_binary_path('simpleperf')
293*288bf522SAndroid Build Coastguard Worker    if not show_gui:
294*288bf522SAndroid Build Coastguard Worker        subprocess.check_call([simpleperf_path, 'report'] + args)
295*288bf522SAndroid Build Coastguard Worker    else:
296*288bf522SAndroid Build Coastguard Worker        report_file = 'perf.report'
297*288bf522SAndroid Build Coastguard Worker        subprocess.check_call([simpleperf_path, 'report', '--full-callgraph'] + args +
298*288bf522SAndroid Build Coastguard Worker                              ['-o', report_file])
299*288bf522SAndroid Build Coastguard Worker        display_report_file(report_file, self_kill_after_sec=self_kill_after_sec)
300*288bf522SAndroid Build Coastguard Worker
301*288bf522SAndroid Build Coastguard Worker
302*288bf522SAndroid Build Coastguard Workerdef get_simpleperf_report_help_msg():
303*288bf522SAndroid Build Coastguard Worker    simpleperf_path = get_host_binary_path('simpleperf')
304*288bf522SAndroid Build Coastguard Worker    args = [simpleperf_path, 'report', '-h']
305*288bf522SAndroid Build Coastguard Worker    proc = subprocess.Popen(args, stdout=subprocess.PIPE)
306*288bf522SAndroid Build Coastguard Worker    (stdoutdata, _) = proc.communicate()
307*288bf522SAndroid Build Coastguard Worker    stdoutdata = bytes_to_str(stdoutdata)
308*288bf522SAndroid Build Coastguard Worker    return stdoutdata[stdoutdata.find('\n') + 1:]
309*288bf522SAndroid Build Coastguard Worker
310*288bf522SAndroid Build Coastguard Worker
311*288bf522SAndroid Build Coastguard Workerdef main():
312*288bf522SAndroid Build Coastguard Worker    self_kill_after_sec = 0
313*288bf522SAndroid Build Coastguard Worker    args = sys.argv[1:]
314*288bf522SAndroid Build Coastguard Worker    if args and args[0] == "--self-kill-for-testing":
315*288bf522SAndroid Build Coastguard Worker        self_kill_after_sec = 1
316*288bf522SAndroid Build Coastguard Worker        args = args[1:]
317*288bf522SAndroid Build Coastguard Worker    if len(args) == 1 and os.path.isfile(args[0]):
318*288bf522SAndroid Build Coastguard Worker        display_report_file(args[0], self_kill_after_sec=self_kill_after_sec)
319*288bf522SAndroid Build Coastguard Worker
320*288bf522SAndroid Build Coastguard Worker    i = 0
321*288bf522SAndroid Build Coastguard Worker    args_for_report_cmd = []
322*288bf522SAndroid Build Coastguard Worker    show_gui = False
323*288bf522SAndroid Build Coastguard Worker    while i < len(args):
324*288bf522SAndroid Build Coastguard Worker        if args[i] == '-h' or args[i] == '--help':
325*288bf522SAndroid Build Coastguard Worker            print('report.py   A python wrapper for simpleperf report command.')
326*288bf522SAndroid Build Coastguard Worker            print('Options supported by simpleperf report command:')
327*288bf522SAndroid Build Coastguard Worker            print(get_simpleperf_report_help_msg())
328*288bf522SAndroid Build Coastguard Worker            print('\nOptions supported by report.py:')
329*288bf522SAndroid Build Coastguard Worker            print('--gui   Show report result in a gui window.')
330*288bf522SAndroid Build Coastguard Worker            print('\nIt also supports showing a report generated by simpleperf report cmd:')
331*288bf522SAndroid Build Coastguard Worker            print('\n  python report.py report_file')
332*288bf522SAndroid Build Coastguard Worker            sys.exit(0)
333*288bf522SAndroid Build Coastguard Worker        elif args[i] == '--gui':
334*288bf522SAndroid Build Coastguard Worker            show_gui = True
335*288bf522SAndroid Build Coastguard Worker            i += 1
336*288bf522SAndroid Build Coastguard Worker        else:
337*288bf522SAndroid Build Coastguard Worker            args_for_report_cmd.append(args[i])
338*288bf522SAndroid Build Coastguard Worker            i += 1
339*288bf522SAndroid Build Coastguard Worker
340*288bf522SAndroid Build Coastguard Worker    call_simpleperf_report(args_for_report_cmd, show_gui, self_kill_after_sec)
341*288bf522SAndroid Build Coastguard Worker
342*288bf522SAndroid Build Coastguard Worker
343*288bf522SAndroid Build Coastguard Workerif __name__ == '__main__':
344*288bf522SAndroid Build Coastguard Worker    main()
345