1# Copyright 2015 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import optparse 6import os 7import random 8import string 9import sys 10 11from devil.android.constants import chrome 12from devil.android import device_utils, device_errors 13 14class OptionParserIgnoreErrors(optparse.OptionParser): 15 """Wrapper for OptionParser that ignores errors and produces no output.""" 16 17 def error(self, msg): 18 pass 19 20 def exit(self, status=0, msg=None): 21 pass 22 23 def print_usage(self, out_file=None): 24 pass 25 26 def print_help(self, out_file=None): 27 pass 28 29 def print_version(self, out_file=None): 30 pass 31 32 33def run_adb_shell(shell_args, device_serial): 34 """Runs "adb shell" with the given arguments. 35 36 Args: 37 shell_args: array of arguments to pass to adb shell. 38 device_serial: if not empty, will add the appropriate command-line 39 parameters so that adb targets the given device. 40 Returns: 41 A tuple containing the adb output (stdout & stderr) and the return code 42 from adb. Will exit if adb fails to start. 43 """ 44 adb_output = [] 45 adb_return_code = 0 46 device = device_utils.DeviceUtils.HealthyDevices(device_arg=device_serial)[0] 47 try: 48 adb_output = device.RunShellCommand(shell_args, shell=False, 49 check_return=True, raw_output=True) 50 except device_errors.AdbShellCommandFailedError as error: 51 adb_return_code = error.status 52 adb_output = error.output 53 54 return (adb_output, adb_return_code) 55 56 57def get_device_sdk_version(): 58 """Uses adb to attempt to determine the SDK version of a running device.""" 59 60 getprop_args = ['getprop', 'ro.build.version.sdk'] 61 62 # get_device_sdk_version() is called before we even parse our command-line 63 # args. Therefore, parse just the device serial number part of the 64 # command-line so we can send the adb command to the correct device. 65 parser = OptionParserIgnoreErrors() 66 parser.add_option('-e', '--serial', dest='device_serial', type='string') 67 options, unused_args = parser.parse_args() # pylint: disable=unused-variable 68 69 success = False 70 71 adb_output, adb_return_code = run_adb_shell(getprop_args, 72 options.device_serial) 73 74 if adb_return_code == 0: 75 # ADB may print output other than the version number (e.g. it chould 76 # print a message about starting the ADB server). 77 # Break the ADB output into white-space delimited segments. 78 parsed_output = str.split(adb_output) 79 if parsed_output: 80 # Assume that the version number is the last thing printed by ADB. 81 version_string = parsed_output[-1] 82 if version_string: 83 try: 84 # Try to convert the text into an integer. 85 version = int(version_string) 86 except ValueError: 87 version = -1 88 else: 89 success = True 90 91 if not success: 92 print >> sys.stderr, adb_output 93 raise Exception("Failed to get device sdk version") 94 95 return version 96 97 98def generate_random_filename_for_test(): 99 """Used for temporary files used in tests. 100 101 Files created from 'NamedTemporaryFile' have inconsistent reuse support across 102 platforms, so it's not guaranteed that they can be reopened. Since many tests 103 communicate files via path, we typically use this method, as well as 104 manual file removal.""" 105 name = ''.join(random.choice(string.ascii_uppercase + 106 string.digits) for _ in range(10)) 107 return os.path.abspath(name) 108 109 110def get_supported_browsers(): 111 """Returns the package names of all supported browsers.""" 112 # Add aliases for backwards compatibility. 113 supported_browsers = { 114 'stable': chrome.PACKAGE_INFO['chrome_stable'], 115 'beta': chrome.PACKAGE_INFO['chrome_beta'], 116 'dev': chrome.PACKAGE_INFO['chrome_dev'], 117 'build': chrome.PACKAGE_INFO['chrome'], 118 } 119 supported_browsers.update(chrome.PACKAGE_INFO) 120 return supported_browsers 121 122 123def get_default_serial(): 124 if 'ANDROID_SERIAL' in os.environ: 125 return os.environ['ANDROID_SERIAL'] 126 return None 127 128 129def get_main_options(parser): 130 parser.add_option('-o', dest='output_file', help='write trace output to FILE', 131 default=None, metavar='FILE') 132 parser.add_option('-t', '--time', dest='trace_time', type='int', 133 help='trace for N seconds', metavar='N') 134 parser.add_option('-j', '--json', dest='write_json', 135 default=False, action='store_true', 136 help='write a JSON file') 137 parser.add_option('--link-assets', dest='link_assets', default=False, 138 action='store_true', 139 help='(deprecated)') 140 parser.add_option('--from-file', dest='from_file', action='store', 141 help='read the trace from a file (compressed) rather than' 142 'running a live trace') 143 parser.add_option('--asset-dir', dest='asset_dir', default='trace-viewer', 144 type='string', help='(deprecated)') 145 parser.add_option('-e', '--serial', dest='device_serial_number', 146 default=get_default_serial(), 147 type='string', help='adb device serial number') 148 parser.add_option('--target', dest='target', default='android', type='string', 149 help='choose tracing target (android or linux)') 150 parser.add_option('--timeout', dest='timeout', type='int', 151 help='timeout for start and stop tracing (seconds)') 152 parser.add_option('--collection-timeout', dest='collection_timeout', 153 type='int', help='timeout for data collection (seconds)') 154 parser.add_option('-a', '--app', dest='app_name', default=None, 155 type='string', action='store', 156 help='enable application-level tracing for ' 157 'comma-separated list of app cmdlines') 158 parser.add_option('-t', '--time', dest='trace_time', type='int', 159 help='trace for N seconds', metavar='N') 160 parser.add_option('-b', '--buf-size', dest='trace_buf_size', 161 type='int', help='use a trace buffer size ' 162 ' of N KB', metavar='N') 163 return parser 164