1927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis#!/usr/bin/env python 2927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis 34b56a2b4acaf00b9c299ab378b52ad8d16c8bc0bJamie Gennis# Copyright (c) 2011 The Chromium Authors. All rights reserved. 44b56a2b4acaf00b9c299ab378b52ad8d16c8bc0bJamie Gennis# Use of this source code is governed by a BSD-style license that can be 54b56a2b4acaf00b9c299ab378b52ad8d16c8bc0bJamie Gennis# found in the LICENSE file. 6927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis 7927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis"""Android system-wide tracing utility. 8927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis 9927914761ffb4ead9d21132154c35d56b6bed787Jamie GennisThis is a tool for capturing a trace that includes data from both userland and 10927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennisthe kernel. It creates an HTML file for visualizing the trace. 11927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis""" 12927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis 132da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport errno, optparse, os, select, subprocess, sys, time, zlib 14927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis 152da489cd246702bee5938545b18a6f710ed214bcJamie Gennisflattened_css_file = 'style.css' 162da489cd246702bee5938545b18a6f710ed214bcJamie Gennisflattened_js_file = 'script.js' 172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 18664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennisclass OptionParserIgnoreErrors(optparse.OptionParser): 19664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis def error(self, msg): 20664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis pass 21664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis 22664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis def exit(self): 23664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis pass 24664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis 25664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis def print_usage(self): 26664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis pass 27664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis 28664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis def print_help(self): 29664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis pass 30664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis 31664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis def print_version(self): 32664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis pass 33664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis 34664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennisdef get_device_sdk_version(): 35664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis getprop_args = ['adb', 'shell', 'getprop', 'ro.build.version.sdk'] 36664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis 37664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis parser = OptionParserIgnoreErrors() 38664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis parser.add_option('-e', '--serial', dest='device_serial', type='string') 39664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis options, args = parser.parse_args() 40664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis if options.device_serial is not None: 41664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis getprop_args[1:1] = ['-s', options.device_serial] 42664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis 43c2a6cae574b71b4b42c8bbbde17ea8796121f0deJamie Gennis adb = subprocess.Popen(getprop_args, stdout=subprocess.PIPE, 44c2a6cae574b71b4b42c8bbbde17ea8796121f0deJamie Gennis stderr=subprocess.PIPE) 45c2a6cae574b71b4b42c8bbbde17ea8796121f0deJamie Gennis out, err = adb.communicate() 46c2a6cae574b71b4b42c8bbbde17ea8796121f0deJamie Gennis if adb.returncode != 0: 47c2a6cae574b71b4b42c8bbbde17ea8796121f0deJamie Gennis print >> sys.stderr, 'Error querying device SDK-version:' 48c2a6cae574b71b4b42c8bbbde17ea8796121f0deJamie Gennis print >> sys.stderr, err 49c2a6cae574b71b4b42c8bbbde17ea8796121f0deJamie Gennis sys.exit(1) 50c2a6cae574b71b4b42c8bbbde17ea8796121f0deJamie Gennis 51c2a6cae574b71b4b42c8bbbde17ea8796121f0deJamie Gennis version = int(out) 52c2a6cae574b71b4b42c8bbbde17ea8796121f0deJamie Gennis return version 53664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis 54de427befa61d2a540c96fa8f19109293e6f566a6Keun young Parkdef add_adb_serial(command, serial): 55de427befa61d2a540c96fa8f19109293e6f566a6Keun young Park if serial != None: 56de427befa61d2a540c96fa8f19109293e6f566a6Keun young Park command.insert(1, serial) 57de427befa61d2a540c96fa8f19109293e6f566a6Keun young Park command.insert(1, '-s') 58de427befa61d2a540c96fa8f19109293e6f566a6Keun young Park 59927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennisdef main(): 60664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis device_sdk_version = get_device_sdk_version() 61664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis if device_sdk_version < 18: 62664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis legacy_script = os.path.join(os.path.dirname(sys.argv[0]), 'systrace-legacy.py') 63664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis os.execv(legacy_script, sys.argv) 64664f21bcaf14044e5e9b09cb7beb8724d18fb851Jamie Gennis 65fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis usage = "Usage: %prog [options] [category1 [category2 ...]]" 66fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis desc = "Example: %prog -b 32768 -t 15 gfx input view sched freq" 67fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis parser = optparse.OptionParser(usage=usage, description=desc) 68927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis parser.add_option('-o', dest='output_file', help='write HTML to FILE', 69927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis default='trace.html', metavar='FILE') 70927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis parser.add_option('-t', '--time', dest='trace_time', type='int', 71927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis help='trace for N seconds', metavar='N') 7298ef97d452aec9ef13a159cb7db96a347b3b2190Jamie Gennis parser.add_option('-b', '--buf-size', dest='trace_buf_size', type='int', 7398ef97d452aec9ef13a159cb7db96a347b3b2190Jamie Gennis help='use a trace buffer size of N KB', metavar='N') 74553ec569391f19c1a0711b42fc89a03d3e670009Jamie Gennis parser.add_option('-k', '--ktrace', dest='kfuncs', action='store', 75553ec569391f19c1a0711b42fc89a03d3e670009Jamie Gennis help='specify a comma-separated list of kernel functions to trace') 76fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis parser.add_option('-l', '--list-categories', dest='list_categories', default=False, 77fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis action='store_true', help='list the available categories and exit') 78b9a5fc88b96d2cd8f6b08c72cc35917e42367969Jamie Gennis parser.add_option('-a', '--app', dest='app_name', default=None, type='string', 79b9a5fc88b96d2cd8f6b08c72cc35917e42367969Jamie Gennis action='store', help='enable application-level tracing for comma-separated ' + 80b9a5fc88b96d2cd8f6b08c72cc35917e42367969Jamie Gennis 'list of app cmdlines') 81fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis 82595ae1e4b47b4a51f2339c2672e63c17d4922a95Jeff Brown parser.add_option('--link-assets', dest='link_assets', default=False, 83595ae1e4b47b4a51f2339c2672e63c17d4922a95Jeff Brown action='store_true', help='link to original CSS or JS resources ' 84595ae1e4b47b4a51f2339c2672e63c17d4922a95Jeff Brown 'instead of embedding them') 85a0cfa1db34523c908b00b443d227b6a516ce2010Glenn Kasten parser.add_option('--from-file', dest='from_file', action='store', 86340d772e8dc47929a927399a343d2218f6f5672cXia Wang help='read the trace from a file (compressed) rather than running a live trace') 872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis parser.add_option('--asset-dir', dest='asset_dir', default='trace-viewer', 882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis type='string', help='') 89de427befa61d2a540c96fa8f19109293e6f566a6Keun young Park parser.add_option('-e', '--serial', dest='device_serial', type='string', 90de427befa61d2a540c96fa8f19109293e6f566a6Keun young Park help='adb device serial number') 91fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis 92927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis options, args = parser.parse_args() 93927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis 94fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis if options.list_categories: 95fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis atrace_args = ['adb', 'shell', 'atrace', '--list_categories'] 96fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis expect_trace = False 97fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis elif options.from_file is not None: 98a0cfa1db34523c908b00b443d227b6a516ce2010Glenn Kasten atrace_args = ['cat', options.from_file] 99fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis expect_trace = True 100fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis else: 101fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis atrace_args = ['adb', 'shell', 'atrace', '-z'] 102fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis expect_trace = True 103fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis 104fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis if options.trace_time is not None: 105fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis if options.trace_time > 0: 106fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis atrace_args.extend(['-t', str(options.trace_time)]) 107fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis else: 108fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis parser.error('the trace time must be a positive number') 109b9a5fc88b96d2cd8f6b08c72cc35917e42367969Jamie Gennis 110fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis if options.trace_buf_size is not None: 111fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis if options.trace_buf_size > 0: 112fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis atrace_args.extend(['-b', str(options.trace_buf_size)]) 113fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis else: 114fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis parser.error('the trace buffer size must be a positive number') 115fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis 116b9a5fc88b96d2cd8f6b08c72cc35917e42367969Jamie Gennis if options.app_name is not None: 117b9a5fc88b96d2cd8f6b08c72cc35917e42367969Jamie Gennis atrace_args.extend(['-a', options.app_name]) 118b9a5fc88b96d2cd8f6b08c72cc35917e42367969Jamie Gennis 119553ec569391f19c1a0711b42fc89a03d3e670009Jamie Gennis if options.kfuncs is not None: 120553ec569391f19c1a0711b42fc89a03d3e670009Jamie Gennis atrace_args.extend(['-k', options.kfuncs]) 121553ec569391f19c1a0711b42fc89a03d3e670009Jamie Gennis 122fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis atrace_args.extend(args) 123fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis 124fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis if atrace_args[0] == 'adb': 125fe4c594d0d9cd87bb0ca43c2b172ec4ab5079ae9Jamie Gennis add_adb_serial(atrace_args, options.device_serial) 126a0cfa1db34523c908b00b443d227b6a516ce2010Glenn Kasten 1274b56a2b4acaf00b9c299ab378b52ad8d16c8bc0bJamie Gennis script_dir = os.path.dirname(os.path.abspath(sys.argv[0])) 128595ae1e4b47b4a51f2339c2672e63c17d4922a95Jeff Brown 129595ae1e4b47b4a51f2339c2672e63c17d4922a95Jeff Brown if options.link_assets: 1302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis src_dir = os.path.join(script_dir, options.asset_dir, 'src') 1312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis build_dir = os.path.join(script_dir, options.asset_dir, 'build') 1322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis js_files, js_flattenizer, css_files = get_assets(src_dir, build_dir) 1342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis css = '\n'.join(linked_css_tag % (os.path.join(src_dir, f)) for f in css_files) 1362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis js = '<script language="javascript">\n%s</script>\n' % js_flattenizer 1372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis js += '\n'.join(linked_js_tag % (os.path.join(src_dir, f)) for f in js_files) 138595ae1e4b47b4a51f2339c2672e63c17d4922a95Jeff Brown else: 1392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis css_filename = os.path.join(script_dir, flattened_css_file) 1402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis js_filename = os.path.join(script_dir, flattened_js_file) 141595ae1e4b47b4a51f2339c2672e63c17d4922a95Jeff Brown css = compiled_css_tag % (open(css_filename).read()) 142595ae1e4b47b4a51f2339c2672e63c17d4922a95Jeff Brown js = compiled_js_tag % (open(js_filename).read()) 1434b56a2b4acaf00b9c299ab378b52ad8d16c8bc0bJamie Gennis 144927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis html_filename = options.output_file 145927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis 1461bf4a4963a2970b80941691b4901e17a47037bd3Jamie Gennis adb = subprocess.Popen(atrace_args, stdout=subprocess.PIPE, 1477e3783f4610cd922712bb67b5ba4c95ed2e71ddbJamie Gennis stderr=subprocess.PIPE) 1489623f136353986b8248e485e7af87661e0b13d54Jamie Gennis 1499623f136353986b8248e485e7af87661e0b13d54Jamie Gennis result = None 1509623f136353986b8248e485e7af87661e0b13d54Jamie Gennis data = [] 1519623f136353986b8248e485e7af87661e0b13d54Jamie Gennis 1529623f136353986b8248e485e7af87661e0b13d54Jamie Gennis # Read the text portion of the output and watch for the 'TRACE:' marker that 1539623f136353986b8248e485e7af87661e0b13d54Jamie Gennis # indicates the start of the trace data. 1549623f136353986b8248e485e7af87661e0b13d54Jamie Gennis while result is None: 1551bf4a4963a2970b80941691b4901e17a47037bd3Jamie Gennis ready = select.select([adb.stdout, adb.stderr], [], [adb.stdout, adb.stderr]) 1561bf4a4963a2970b80941691b4901e17a47037bd3Jamie Gennis if adb.stderr in ready[0]: 1571bf4a4963a2970b80941691b4901e17a47037bd3Jamie Gennis err = os.read(adb.stderr.fileno(), 4096) 1581bf4a4963a2970b80941691b4901e17a47037bd3Jamie Gennis sys.stderr.write(err) 1591bf4a4963a2970b80941691b4901e17a47037bd3Jamie Gennis sys.stderr.flush() 1601bf4a4963a2970b80941691b4901e17a47037bd3Jamie Gennis if adb.stdout in ready[0]: 1619623f136353986b8248e485e7af87661e0b13d54Jamie Gennis out = os.read(adb.stdout.fileno(), 4096) 1629623f136353986b8248e485e7af87661e0b13d54Jamie Gennis parts = out.split('\nTRACE:', 1) 1639623f136353986b8248e485e7af87661e0b13d54Jamie Gennis 1649623f136353986b8248e485e7af87661e0b13d54Jamie Gennis txt = parts[0].replace('\r', '') 1659623f136353986b8248e485e7af87661e0b13d54Jamie Gennis if len(parts) == 2: 1669623f136353986b8248e485e7af87661e0b13d54Jamie Gennis # The '\nTRACE:' match stole the last newline from the text, so add it 1679623f136353986b8248e485e7af87661e0b13d54Jamie Gennis # back here. 1689623f136353986b8248e485e7af87661e0b13d54Jamie Gennis txt += '\n' 1699623f136353986b8248e485e7af87661e0b13d54Jamie Gennis sys.stdout.write(txt) 1709623f136353986b8248e485e7af87661e0b13d54Jamie Gennis sys.stdout.flush() 1719623f136353986b8248e485e7af87661e0b13d54Jamie Gennis 1729623f136353986b8248e485e7af87661e0b13d54Jamie Gennis if len(parts) == 2: 1739623f136353986b8248e485e7af87661e0b13d54Jamie Gennis data.append(parts[1]) 1749623f136353986b8248e485e7af87661e0b13d54Jamie Gennis sys.stdout.write("downloading trace...") 1759623f136353986b8248e485e7af87661e0b13d54Jamie Gennis sys.stdout.flush() 1769623f136353986b8248e485e7af87661e0b13d54Jamie Gennis break 1779623f136353986b8248e485e7af87661e0b13d54Jamie Gennis 1781bf4a4963a2970b80941691b4901e17a47037bd3Jamie Gennis result = adb.poll() 1799623f136353986b8248e485e7af87661e0b13d54Jamie Gennis 1809623f136353986b8248e485e7af87661e0b13d54Jamie Gennis # Read and buffer the data portion of the output. 18118bb528287dd9407583346b9826de4a433481131Jamie Gennis while True: 1829623f136353986b8248e485e7af87661e0b13d54Jamie Gennis ready = select.select([adb.stdout, adb.stderr], [], [adb.stdout, adb.stderr]) 18318bb528287dd9407583346b9826de4a433481131Jamie Gennis keepReading = False 1849623f136353986b8248e485e7af87661e0b13d54Jamie Gennis if adb.stderr in ready[0]: 1859623f136353986b8248e485e7af87661e0b13d54Jamie Gennis err = os.read(adb.stderr.fileno(), 4096) 18618bb528287dd9407583346b9826de4a433481131Jamie Gennis if len(err) > 0: 18718bb528287dd9407583346b9826de4a433481131Jamie Gennis keepReading = True 18818bb528287dd9407583346b9826de4a433481131Jamie Gennis sys.stderr.write(err) 18918bb528287dd9407583346b9826de4a433481131Jamie Gennis sys.stderr.flush() 1909623f136353986b8248e485e7af87661e0b13d54Jamie Gennis if adb.stdout in ready[0]: 1919623f136353986b8248e485e7af87661e0b13d54Jamie Gennis out = os.read(adb.stdout.fileno(), 4096) 19218bb528287dd9407583346b9826de4a433481131Jamie Gennis if len(out) > 0: 19318bb528287dd9407583346b9826de4a433481131Jamie Gennis keepReading = True 19418bb528287dd9407583346b9826de4a433481131Jamie Gennis data.append(out) 19518bb528287dd9407583346b9826de4a433481131Jamie Gennis 19618bb528287dd9407583346b9826de4a433481131Jamie Gennis if result is not None and not keepReading: 19718bb528287dd9407583346b9826de4a433481131Jamie Gennis break 1989623f136353986b8248e485e7af87661e0b13d54Jamie Gennis 1999623f136353986b8248e485e7af87661e0b13d54Jamie Gennis result = adb.poll() 2009623f136353986b8248e485e7af87661e0b13d54Jamie Gennis 2019623f136353986b8248e485e7af87661e0b13d54Jamie Gennis if result == 0: 2029623f136353986b8248e485e7af87661e0b13d54Jamie Gennis if expect_trace: 2039623f136353986b8248e485e7af87661e0b13d54Jamie Gennis data = ''.join(data) 2049623f136353986b8248e485e7af87661e0b13d54Jamie Gennis 2059623f136353986b8248e485e7af87661e0b13d54Jamie Gennis # Collapse CRLFs that are added by adb shell. 2069623f136353986b8248e485e7af87661e0b13d54Jamie Gennis if data.startswith('\r\n'): 2079623f136353986b8248e485e7af87661e0b13d54Jamie Gennis data = data.replace('\r\n', '\n') 2089623f136353986b8248e485e7af87661e0b13d54Jamie Gennis 2099623f136353986b8248e485e7af87661e0b13d54Jamie Gennis # Skip the initial newline. 2109623f136353986b8248e485e7af87661e0b13d54Jamie Gennis data = data[1:] 2119623f136353986b8248e485e7af87661e0b13d54Jamie Gennis 2129623f136353986b8248e485e7af87661e0b13d54Jamie Gennis if not data: 2139623f136353986b8248e485e7af87661e0b13d54Jamie Gennis print >> sys.stderr, ('No data was captured. Output file was not ' + 2149623f136353986b8248e485e7af87661e0b13d54Jamie Gennis 'written.') 2159623f136353986b8248e485e7af87661e0b13d54Jamie Gennis sys.exit(1) 2169623f136353986b8248e485e7af87661e0b13d54Jamie Gennis else: 2179623f136353986b8248e485e7af87661e0b13d54Jamie Gennis # Indicate to the user that the data download is complete. 2189623f136353986b8248e485e7af87661e0b13d54Jamie Gennis print " done\n" 2199623f136353986b8248e485e7af87661e0b13d54Jamie Gennis 2209623f136353986b8248e485e7af87661e0b13d54Jamie Gennis html_file = open(html_filename, 'w') 2219623f136353986b8248e485e7af87661e0b13d54Jamie Gennis html_file.write(html_prefix % (css, js)) 2229623f136353986b8248e485e7af87661e0b13d54Jamie Gennis 2239623f136353986b8248e485e7af87661e0b13d54Jamie Gennis size = 4096 2249623f136353986b8248e485e7af87661e0b13d54Jamie Gennis dec = zlib.decompressobj() 2259623f136353986b8248e485e7af87661e0b13d54Jamie Gennis for chunk in (data[i:i+size] for i in xrange(0, len(data), size)): 2269623f136353986b8248e485e7af87661e0b13d54Jamie Gennis decoded_chunk = dec.decompress(chunk) 2279623f136353986b8248e485e7af87661e0b13d54Jamie Gennis html_chunk = decoded_chunk.replace('\n', '\\n\\\n') 2289623f136353986b8248e485e7af87661e0b13d54Jamie Gennis html_file.write(html_chunk) 2299623f136353986b8248e485e7af87661e0b13d54Jamie Gennis 2309623f136353986b8248e485e7af87661e0b13d54Jamie Gennis html_out = dec.flush().replace('\n', '\\n\\\n') 231bf3e61646bc175280d3a23f465a30590238c684cJamie Gennis html_file.write(html_out) 2329623f136353986b8248e485e7af87661e0b13d54Jamie Gennis html_file.write(html_suffix) 2339623f136353986b8248e485e7af87661e0b13d54Jamie Gennis html_file.close() 2349623f136353986b8248e485e7af87661e0b13d54Jamie Gennis print "\n wrote file://%s/%s\n" % (os.getcwd(), options.output_file) 2359623f136353986b8248e485e7af87661e0b13d54Jamie Gennis 2369623f136353986b8248e485e7af87661e0b13d54Jamie Gennis else: # i.e. result != 0 2379623f136353986b8248e485e7af87661e0b13d54Jamie Gennis print >> sys.stderr, 'adb returned error code %d' % result 2389623f136353986b8248e485e7af87661e0b13d54Jamie Gennis sys.exit(1) 239927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis 2402da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef get_assets(src_dir, build_dir): 2412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis sys.path.append(build_dir) 2422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis gen = __import__('generate_standalone_timeline_view', {}, {}) 2432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis parse_deps = __import__('parse_deps', {}, {}) 2442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis filenames = gen._get_input_filenames() 2459623f136353986b8248e485e7af87661e0b13d54Jamie Gennis load_sequence = parse_deps.calc_load_sequence(filenames, src_dir) 2462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis js_files = [] 2482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis js_flattenizer = "window.FLATTENED = {};\n" 2492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis css_files = [] 2502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for module in load_sequence: 2522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis js_files.append(os.path.relpath(module.filename, src_dir)) 2532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis js_flattenizer += "window.FLATTENED['%s'] = true;\n" % module.name 2542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for style_sheet in module.style_sheets: 2552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis css_files.append(os.path.relpath(style_sheet.filename, src_dir)) 2562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis sys.path.pop() 2582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return (js_files, js_flattenizer, css_files) 2602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 261927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennishtml_prefix = """<!DOCTYPE HTML> 262927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis<html> 263927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis<head i18n-values="dir:textdirection;"> 264b9a5fc88b96d2cd8f6b08c72cc35917e42367969Jamie Gennis<meta charset="utf-8"/> 265927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis<title>Android System Trace</title> 266595ae1e4b47b4a51f2339c2672e63c17d4922a95Jeff Brown%s 267595ae1e4b47b4a51f2339c2672e63c17d4922a95Jeff Brown%s 2682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis<script language="javascript"> 2692da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdocument.addEventListener('DOMContentLoaded', function() { 2702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!linuxPerfData) 2712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 2722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 27388448d9ae4dfff1805045790ef5f32495d62abccJeff Brown var m = new tracing.Model(linuxPerfData); 2742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var timelineViewEl = document.querySelector('.view'); 27588448d9ae4dfff1805045790ef5f32495d62abccJeff Brown tracing.ui.decorate(timelineViewEl, tracing.TimelineView); 2762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis timelineViewEl.model = m; 2772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis timelineViewEl.tabIndex = 1; 2782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis timelineViewEl.timeline.focusElement = timelineViewEl; 2792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis}); 2802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis</script> 281927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis<style> 282927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis .view { 283927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis overflow: hidden; 284927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis position: absolute; 285927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis top: 0; 286927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis bottom: 0; 287927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis left: 0; 288927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis right: 0; 289927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis } 290927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis</style> 291927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis</head> 292927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis<body> 293927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis <div class="view"> 294927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis </div> 2952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis<!-- BEGIN TRACE --> 296927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis <script> 297927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis var linuxPerfData = "\\ 298927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis""" 299927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis 3002da489cd246702bee5938545b18a6f710ed214bcJamie Gennishtml_suffix = """\\n"; 301927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis </script> 3022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis<!-- END TRACE --> 303927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis</body> 304927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis</html> 305927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis""" 306927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis 307595ae1e4b47b4a51f2339c2672e63c17d4922a95Jeff Browncompiled_css_tag = """<style type="text/css">%s</style>""" 308595ae1e4b47b4a51f2339c2672e63c17d4922a95Jeff Browncompiled_js_tag = """<script language="javascript">%s</script>""" 309595ae1e4b47b4a51f2339c2672e63c17d4922a95Jeff Brown 310595ae1e4b47b4a51f2339c2672e63c17d4922a95Jeff Brownlinked_css_tag = """<link rel="stylesheet" href="%s"></link>""" 311595ae1e4b47b4a51f2339c2672e63c17d4922a95Jeff Brownlinked_js_tag = """<script language="javascript" src="%s"></script>""" 312595ae1e4b47b4a51f2339c2672e63c17d4922a95Jeff Brown 313927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennisif __name__ == '__main__': 314927914761ffb4ead9d21132154c35d56b6bed787Jamie Gennis main() 315