| # Copyright 2015 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import optparse |
| import os |
| import sys |
| |
| from devil.android.constants import chrome |
| from devil.android import device_utils, device_errors |
| |
| class OptionParserIgnoreErrors(optparse.OptionParser): |
| """Wrapper for OptionParser that ignores errors and produces no output.""" |
| |
| def error(self, msg): |
| pass |
| |
| def exit(self, status=0, msg=None): |
| pass |
| |
| def print_usage(self, out_file=None): |
| pass |
| |
| def print_help(self, out_file=None): |
| pass |
| |
| def print_version(self, out_file=None): |
| pass |
| |
| |
| def run_adb_shell(shell_args, device_serial): |
| """Runs "adb shell" with the given arguments. |
| |
| Args: |
| shell_args: array of arguments to pass to adb shell. |
| device_serial: if not empty, will add the appropriate command-line |
| parameters so that adb targets the given device. |
| Returns: |
| A tuple containing the adb output (stdout & stderr) and the return code |
| from adb. Will exit if adb fails to start. |
| """ |
| adb_output = [] |
| adb_return_code = 0 |
| device = device_utils.DeviceUtils.HealthyDevices(device_arg=device_serial)[0] |
| try: |
| adb_output = device.RunShellCommand(shell_args, shell=False, |
| check_return=True, raw_output=True) |
| except device_errors.AdbShellCommandFailedError as error: |
| adb_return_code = error.status |
| adb_output = error.output |
| |
| return (adb_output, adb_return_code) |
| |
| |
| def get_tracing_path(device_serial=None): |
| """Uses adb to attempt to determine tracing path. The newest kernel doesn't |
| support mounting debugfs, so the Android master uses tracefs to replace it. |
| |
| Returns: |
| /sys/kernel/debug/tracing for device with debugfs mount support; |
| /sys/kernel/tracing for device with tracefs support; |
| /sys/kernel/debug/tracing if support can't be determined. |
| """ |
| mount_info_args = ['mount'] |
| |
| if device_serial is None: |
| parser = OptionParserIgnoreErrors() |
| parser.add_option('-e', '--serial', dest='device_serial', type='string') |
| options, _ = parser.parse_args() |
| device_serial = options.device_serial |
| |
| adb_output, adb_return_code = run_adb_shell(mount_info_args, device_serial, ) |
| if adb_return_code == 0 and 'tracefs on /sys/kernel/tracing' in adb_output: |
| return '/sys/kernel/tracing' |
| return '/sys/kernel/debug/tracing' |
| |
| |
| def get_device_sdk_version(): |
| """Uses adb to attempt to determine the SDK version of a running device.""" |
| |
| getprop_args = ['getprop', 'ro.build.version.sdk'] |
| |
| # get_device_sdk_version() is called before we even parse our command-line |
| # args. Therefore, parse just the device serial number part of the |
| # command-line so we can send the adb command to the correct device. |
| parser = OptionParserIgnoreErrors() |
| parser.add_option('-e', '--serial', dest='device_serial', type='string') |
| options, unused_args = parser.parse_args() # pylint: disable=unused-variable |
| |
| success = False |
| |
| adb_output, adb_return_code = run_adb_shell(getprop_args, |
| options.device_serial) |
| |
| if adb_return_code == 0: |
| # ADB may print output other than the version number (e.g. it chould |
| # print a message about starting the ADB server). |
| # Break the ADB output into white-space delimited segments. |
| parsed_output = str.split(adb_output) |
| if parsed_output: |
| # Assume that the version number is the last thing printed by ADB. |
| version_string = parsed_output[-1] |
| if version_string: |
| try: |
| # Try to convert the text into an integer. |
| version = int(version_string) |
| except ValueError: |
| version = -1 |
| else: |
| success = True |
| |
| if not success: |
| print >> sys.stderr, adb_output |
| raise Exception("Failed to get device sdk version") |
| |
| return version |
| |
| |
| def get_supported_browsers(): |
| """Returns the package names of all supported browsers.""" |
| # Add aliases for backwards compatibility. |
| supported_browsers = { |
| 'stable': chrome.PACKAGE_INFO['chrome_stable'], |
| 'beta': chrome.PACKAGE_INFO['chrome_beta'], |
| 'dev': chrome.PACKAGE_INFO['chrome_dev'], |
| 'build': chrome.PACKAGE_INFO['chrome'], |
| } |
| supported_browsers.update(chrome.PACKAGE_INFO) |
| return supported_browsers |
| |
| |
| def get_default_serial(): |
| if 'ANDROID_SERIAL' in os.environ: |
| return os.environ['ANDROID_SERIAL'] |
| return None |
| |
| |
| def get_main_options(parser): |
| parser.add_option('-o', dest='output_file', help='write trace output to FILE', |
| default=None, metavar='FILE') |
| parser.add_option('-t', '--time', dest='trace_time', type='int', |
| help='trace for N seconds', metavar='N') |
| parser.add_option('-j', '--json', dest='write_json', |
| default=False, action='store_true', |
| help='write a JSON file') |
| parser.add_option('--link-assets', dest='link_assets', default=False, |
| action='store_true', |
| help='(deprecated)') |
| parser.add_option('--from-file', dest='from_file', action='store', |
| help='read the trace from a file (compressed) rather than' |
| 'running a live trace') |
| parser.add_option('--asset-dir', dest='asset_dir', default='trace-viewer', |
| type='string', help='(deprecated)') |
| parser.add_option('-e', '--serial', dest='device_serial_number', |
| default=get_default_serial(), |
| type='string', help='adb device serial number') |
| parser.add_option('--target', dest='target', default='android', type='string', |
| help='choose tracing target (android or linux)') |
| parser.add_option('--timeout', dest='timeout', type='int', |
| help='timeout for start and stop tracing (seconds)') |
| parser.add_option('--collection-timeout', dest='collection_timeout', |
| type='int', help='timeout for data collection (seconds)') |
| parser.add_option('-a', '--app', dest='app_name', default=None, |
| type='string', action='store', |
| help='enable application-level tracing for ' |
| 'comma-separated list of app cmdlines') |
| parser.add_option('-t', '--time', dest='trace_time', type='int', |
| help='trace for N seconds', metavar='N') |
| parser.add_option('-b', '--buf-size', dest='trace_buf_size', |
| type='int', help='use a trace buffer size ' |
| ' of N KB', metavar='N') |
| return parser |