1*8975f5c5SAndroid Build Coastguard Worker#!/usr/bin/env vpython3 2*8975f5c5SAndroid Build Coastguard Worker# 3*8975f5c5SAndroid Build Coastguard Worker# Copyright 2013 The Chromium Authors 4*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 5*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file. 6*8975f5c5SAndroid Build Coastguard Worker 7*8975f5c5SAndroid Build Coastguard Worker"""Provisions Android devices with settings required for bots. 8*8975f5c5SAndroid Build Coastguard Worker 9*8975f5c5SAndroid Build Coastguard WorkerUsage: 10*8975f5c5SAndroid Build Coastguard Worker ./provision_devices.py [-d <device serial number>] 11*8975f5c5SAndroid Build Coastguard Worker""" 12*8975f5c5SAndroid Build Coastguard Worker 13*8975f5c5SAndroid Build Coastguard Workerimport argparse 14*8975f5c5SAndroid Build Coastguard Workerimport datetime 15*8975f5c5SAndroid Build Coastguard Workerimport json 16*8975f5c5SAndroid Build Coastguard Workerimport logging 17*8975f5c5SAndroid Build Coastguard Workerimport os 18*8975f5c5SAndroid Build Coastguard Workerimport posixpath 19*8975f5c5SAndroid Build Coastguard Workerimport re 20*8975f5c5SAndroid Build Coastguard Workerimport subprocess 21*8975f5c5SAndroid Build Coastguard Workerimport sys 22*8975f5c5SAndroid Build Coastguard Workerimport time 23*8975f5c5SAndroid Build Coastguard Worker 24*8975f5c5SAndroid Build Coastguard Worker# Import _strptime before threaded code. datetime.datetime.strptime is 25*8975f5c5SAndroid Build Coastguard Worker# threadsafe except for the initial import of the _strptime module. 26*8975f5c5SAndroid Build Coastguard Worker# See crbug.com/584730 and https://bugs.python.org/issue7980. 27*8975f5c5SAndroid Build Coastguard Workerimport _strptime # pylint: disable=unused-import 28*8975f5c5SAndroid Build Coastguard Worker 29*8975f5c5SAndroid Build Coastguard Workerimport devil_chromium 30*8975f5c5SAndroid Build Coastguard Workerfrom devil.android import battery_utils 31*8975f5c5SAndroid Build Coastguard Workerfrom devil.android import device_denylist 32*8975f5c5SAndroid Build Coastguard Workerfrom devil.android import device_errors 33*8975f5c5SAndroid Build Coastguard Workerfrom devil.android import device_temp_file 34*8975f5c5SAndroid Build Coastguard Workerfrom devil.android import device_utils 35*8975f5c5SAndroid Build Coastguard Workerfrom devil.android.sdk import keyevent 36*8975f5c5SAndroid Build Coastguard Workerfrom devil.android.sdk import version_codes 37*8975f5c5SAndroid Build Coastguard Workerfrom devil.constants import exit_codes 38*8975f5c5SAndroid Build Coastguard Workerfrom devil.utils import run_tests_helper 39*8975f5c5SAndroid Build Coastguard Workerfrom devil.utils import timeout_retry 40*8975f5c5SAndroid Build Coastguard Workerfrom pylib import constants 41*8975f5c5SAndroid Build Coastguard Workerfrom pylib import device_settings 42*8975f5c5SAndroid Build Coastguard Workerfrom pylib.constants import host_paths 43*8975f5c5SAndroid Build Coastguard Worker 44*8975f5c5SAndroid Build Coastguard Worker_SYSTEM_WEBVIEW_PATHS = ['/system/app/webview', '/system/app/WebViewGoogle'] 45*8975f5c5SAndroid Build Coastguard Worker_CHROME_PACKAGE_REGEX = re.compile('.*chrom.*') 46*8975f5c5SAndroid Build Coastguard Worker_TOMBSTONE_REGEX = re.compile('tombstone.*') 47*8975f5c5SAndroid Build Coastguard Worker 48*8975f5c5SAndroid Build Coastguard Worker 49*8975f5c5SAndroid Build Coastguard Workerclass _DEFAULT_TIMEOUTS: 50*8975f5c5SAndroid Build Coastguard Worker # L can take a while to reboot after a wipe. 51*8975f5c5SAndroid Build Coastguard Worker LOLLIPOP = 600 52*8975f5c5SAndroid Build Coastguard Worker PRE_LOLLIPOP = 180 53*8975f5c5SAndroid Build Coastguard Worker 54*8975f5c5SAndroid Build Coastguard Worker HELP_TEXT = '{}s on L, {}s on pre-L'.format(LOLLIPOP, PRE_LOLLIPOP) 55*8975f5c5SAndroid Build Coastguard Worker 56*8975f5c5SAndroid Build Coastguard Worker 57*8975f5c5SAndroid Build Coastguard Workerclass _PHASES: 58*8975f5c5SAndroid Build Coastguard Worker WIPE = 'wipe' 59*8975f5c5SAndroid Build Coastguard Worker PROPERTIES = 'properties' 60*8975f5c5SAndroid Build Coastguard Worker FINISH = 'finish' 61*8975f5c5SAndroid Build Coastguard Worker 62*8975f5c5SAndroid Build Coastguard Worker ALL = [WIPE, PROPERTIES, FINISH] 63*8975f5c5SAndroid Build Coastguard Worker 64*8975f5c5SAndroid Build Coastguard Worker 65*8975f5c5SAndroid Build Coastguard Workerdef ProvisionDevices(args): 66*8975f5c5SAndroid Build Coastguard Worker denylist = (device_denylist.Denylist(args.denylist_file) 67*8975f5c5SAndroid Build Coastguard Worker if args.denylist_file else None) 68*8975f5c5SAndroid Build Coastguard Worker devices = [ 69*8975f5c5SAndroid Build Coastguard Worker d for d in device_utils.DeviceUtils.HealthyDevices(denylist) 70*8975f5c5SAndroid Build Coastguard Worker if not args.emulators or d.is_emulator 71*8975f5c5SAndroid Build Coastguard Worker ] 72*8975f5c5SAndroid Build Coastguard Worker if args.device: 73*8975f5c5SAndroid Build Coastguard Worker devices = [d for d in devices if d == args.device] 74*8975f5c5SAndroid Build Coastguard Worker if not devices: 75*8975f5c5SAndroid Build Coastguard Worker raise device_errors.DeviceUnreachableError(args.device) 76*8975f5c5SAndroid Build Coastguard Worker parallel_devices = device_utils.DeviceUtils.parallel(devices) 77*8975f5c5SAndroid Build Coastguard Worker if args.emulators: 78*8975f5c5SAndroid Build Coastguard Worker parallel_devices.pMap(SetProperties, args) 79*8975f5c5SAndroid Build Coastguard Worker else: 80*8975f5c5SAndroid Build Coastguard Worker parallel_devices.pMap(ProvisionDevice, denylist, args) 81*8975f5c5SAndroid Build Coastguard Worker if args.auto_reconnect: 82*8975f5c5SAndroid Build Coastguard Worker _LaunchHostHeartbeat() 83*8975f5c5SAndroid Build Coastguard Worker denylisted_devices = denylist.Read() if denylist else [] 84*8975f5c5SAndroid Build Coastguard Worker if args.output_device_denylist: 85*8975f5c5SAndroid Build Coastguard Worker with open(args.output_device_denylist, 'w') as f: 86*8975f5c5SAndroid Build Coastguard Worker json.dump(denylisted_devices, f) 87*8975f5c5SAndroid Build Coastguard Worker if all(d in denylisted_devices for d in devices): 88*8975f5c5SAndroid Build Coastguard Worker raise device_errors.NoDevicesError 89*8975f5c5SAndroid Build Coastguard Worker return 0 90*8975f5c5SAndroid Build Coastguard Worker 91*8975f5c5SAndroid Build Coastguard Worker 92*8975f5c5SAndroid Build Coastguard Workerdef ProvisionDevice(device, denylist, options): 93*8975f5c5SAndroid Build Coastguard Worker def should_run_phase(phase_name): 94*8975f5c5SAndroid Build Coastguard Worker return not options.phases or phase_name in options.phases 95*8975f5c5SAndroid Build Coastguard Worker 96*8975f5c5SAndroid Build Coastguard Worker def run_phase(phase_func, reboot_timeout, reboot=True): 97*8975f5c5SAndroid Build Coastguard Worker try: 98*8975f5c5SAndroid Build Coastguard Worker device.WaitUntilFullyBooted(timeout=reboot_timeout, retries=0) 99*8975f5c5SAndroid Build Coastguard Worker except device_errors.CommandTimeoutError: 100*8975f5c5SAndroid Build Coastguard Worker logging.error('Device did not finish booting. Will try to reboot.') 101*8975f5c5SAndroid Build Coastguard Worker device.Reboot(timeout=reboot_timeout) 102*8975f5c5SAndroid Build Coastguard Worker phase_func(device, options) 103*8975f5c5SAndroid Build Coastguard Worker if reboot: 104*8975f5c5SAndroid Build Coastguard Worker device.Reboot(False, retries=0) 105*8975f5c5SAndroid Build Coastguard Worker device.adb.WaitForDevice() 106*8975f5c5SAndroid Build Coastguard Worker 107*8975f5c5SAndroid Build Coastguard Worker try: 108*8975f5c5SAndroid Build Coastguard Worker if options.reboot_timeout: 109*8975f5c5SAndroid Build Coastguard Worker reboot_timeout = options.reboot_timeout 110*8975f5c5SAndroid Build Coastguard Worker elif device.build_version_sdk >= version_codes.LOLLIPOP: 111*8975f5c5SAndroid Build Coastguard Worker reboot_timeout = _DEFAULT_TIMEOUTS.LOLLIPOP 112*8975f5c5SAndroid Build Coastguard Worker else: 113*8975f5c5SAndroid Build Coastguard Worker reboot_timeout = _DEFAULT_TIMEOUTS.PRE_LOLLIPOP 114*8975f5c5SAndroid Build Coastguard Worker 115*8975f5c5SAndroid Build Coastguard Worker if should_run_phase(_PHASES.WIPE): 116*8975f5c5SAndroid Build Coastguard Worker if (options.chrome_specific_wipe or device.IsUserBuild() or 117*8975f5c5SAndroid Build Coastguard Worker device.build_version_sdk >= version_codes.MARSHMALLOW): 118*8975f5c5SAndroid Build Coastguard Worker run_phase(WipeChromeData, reboot_timeout) 119*8975f5c5SAndroid Build Coastguard Worker else: 120*8975f5c5SAndroid Build Coastguard Worker run_phase(WipeDevice, reboot_timeout) 121*8975f5c5SAndroid Build Coastguard Worker 122*8975f5c5SAndroid Build Coastguard Worker if should_run_phase(_PHASES.PROPERTIES): 123*8975f5c5SAndroid Build Coastguard Worker run_phase(SetProperties, reboot_timeout) 124*8975f5c5SAndroid Build Coastguard Worker 125*8975f5c5SAndroid Build Coastguard Worker if should_run_phase(_PHASES.FINISH): 126*8975f5c5SAndroid Build Coastguard Worker run_phase(FinishProvisioning, reboot_timeout, reboot=False) 127*8975f5c5SAndroid Build Coastguard Worker 128*8975f5c5SAndroid Build Coastguard Worker if options.chrome_specific_wipe: 129*8975f5c5SAndroid Build Coastguard Worker package = "com.google.android.gms" 130*8975f5c5SAndroid Build Coastguard Worker version_name = device.GetApplicationVersion(package) 131*8975f5c5SAndroid Build Coastguard Worker logging.info("Version name for %s is %s", package, version_name) 132*8975f5c5SAndroid Build Coastguard Worker 133*8975f5c5SAndroid Build Coastguard Worker CheckExternalStorage(device) 134*8975f5c5SAndroid Build Coastguard Worker 135*8975f5c5SAndroid Build Coastguard Worker except device_errors.CommandTimeoutError: 136*8975f5c5SAndroid Build Coastguard Worker logging.exception('Timed out waiting for device %s. Adding to denylist.', 137*8975f5c5SAndroid Build Coastguard Worker str(device)) 138*8975f5c5SAndroid Build Coastguard Worker if denylist: 139*8975f5c5SAndroid Build Coastguard Worker denylist.Extend([str(device)], reason='provision_timeout') 140*8975f5c5SAndroid Build Coastguard Worker 141*8975f5c5SAndroid Build Coastguard Worker except (device_errors.CommandFailedError, 142*8975f5c5SAndroid Build Coastguard Worker device_errors.DeviceUnreachableError): 143*8975f5c5SAndroid Build Coastguard Worker logging.exception('Failed to provision device %s. Adding to denylist.', 144*8975f5c5SAndroid Build Coastguard Worker str(device)) 145*8975f5c5SAndroid Build Coastguard Worker if denylist: 146*8975f5c5SAndroid Build Coastguard Worker denylist.Extend([str(device)], reason='provision_failure') 147*8975f5c5SAndroid Build Coastguard Worker 148*8975f5c5SAndroid Build Coastguard Worker 149*8975f5c5SAndroid Build Coastguard Workerdef CheckExternalStorage(device): 150*8975f5c5SAndroid Build Coastguard Worker """Checks that storage is writable and if not makes it writable. 151*8975f5c5SAndroid Build Coastguard Worker 152*8975f5c5SAndroid Build Coastguard Worker Arguments: 153*8975f5c5SAndroid Build Coastguard Worker device: The device to check. 154*8975f5c5SAndroid Build Coastguard Worker """ 155*8975f5c5SAndroid Build Coastguard Worker try: 156*8975f5c5SAndroid Build Coastguard Worker with device_temp_file.DeviceTempFile( 157*8975f5c5SAndroid Build Coastguard Worker device.adb, suffix='.sh', dir=device.GetExternalStoragePath()) as f: 158*8975f5c5SAndroid Build Coastguard Worker device.WriteFile(f.name, 'test') 159*8975f5c5SAndroid Build Coastguard Worker except device_errors.CommandFailedError: 160*8975f5c5SAndroid Build Coastguard Worker logging.info('External storage not writable. Remounting / as RW') 161*8975f5c5SAndroid Build Coastguard Worker device.RunShellCommand(['mount', '-o', 'remount,rw', '/'], 162*8975f5c5SAndroid Build Coastguard Worker check_return=True, as_root=True) 163*8975f5c5SAndroid Build Coastguard Worker device.EnableRoot() 164*8975f5c5SAndroid Build Coastguard Worker with device_temp_file.DeviceTempFile( 165*8975f5c5SAndroid Build Coastguard Worker device.adb, suffix='.sh', dir=device.GetExternalStoragePath()) as f: 166*8975f5c5SAndroid Build Coastguard Worker device.WriteFile(f.name, 'test') 167*8975f5c5SAndroid Build Coastguard Worker 168*8975f5c5SAndroid Build Coastguard Workerdef WipeChromeData(device, options): 169*8975f5c5SAndroid Build Coastguard Worker """Wipes chrome specific data from device 170*8975f5c5SAndroid Build Coastguard Worker 171*8975f5c5SAndroid Build Coastguard Worker (1) uninstall any app whose name matches *chrom*, except 172*8975f5c5SAndroid Build Coastguard Worker com.android.chrome, which is the chrome stable package. Doing so also 173*8975f5c5SAndroid Build Coastguard Worker removes the corresponding dirs under /data/data/ and /data/app/ 174*8975f5c5SAndroid Build Coastguard Worker (2) remove any dir under /data/app-lib/ whose name matches *chrom* 175*8975f5c5SAndroid Build Coastguard Worker (3) remove any files under /data/tombstones/ whose name matches "tombstone*" 176*8975f5c5SAndroid Build Coastguard Worker (4) remove /data/local.prop if there is any 177*8975f5c5SAndroid Build Coastguard Worker (5) remove /data/local/chrome-command-line if there is any 178*8975f5c5SAndroid Build Coastguard Worker (6) remove anything under /data/local/.config/ if the dir exists 179*8975f5c5SAndroid Build Coastguard Worker (this is telemetry related) 180*8975f5c5SAndroid Build Coastguard Worker (7) remove anything under /data/local/tmp/ 181*8975f5c5SAndroid Build Coastguard Worker 182*8975f5c5SAndroid Build Coastguard Worker Arguments: 183*8975f5c5SAndroid Build Coastguard Worker device: the device to wipe 184*8975f5c5SAndroid Build Coastguard Worker """ 185*8975f5c5SAndroid Build Coastguard Worker if options.skip_wipe: 186*8975f5c5SAndroid Build Coastguard Worker return 187*8975f5c5SAndroid Build Coastguard Worker 188*8975f5c5SAndroid Build Coastguard Worker try: 189*8975f5c5SAndroid Build Coastguard Worker if device.IsUserBuild(): 190*8975f5c5SAndroid Build Coastguard Worker _UninstallIfMatch(device, _CHROME_PACKAGE_REGEX, 191*8975f5c5SAndroid Build Coastguard Worker constants.PACKAGE_INFO['chrome_stable'].package) 192*8975f5c5SAndroid Build Coastguard Worker device.RunShellCommand('rm -rf %s/*' % device.GetExternalStoragePath(), 193*8975f5c5SAndroid Build Coastguard Worker check_return=True) 194*8975f5c5SAndroid Build Coastguard Worker device.RunShellCommand('rm -rf /data/local/tmp/*', check_return=True) 195*8975f5c5SAndroid Build Coastguard Worker else: 196*8975f5c5SAndroid Build Coastguard Worker device.EnableRoot() 197*8975f5c5SAndroid Build Coastguard Worker _UninstallIfMatch(device, _CHROME_PACKAGE_REGEX, 198*8975f5c5SAndroid Build Coastguard Worker constants.PACKAGE_INFO['chrome_stable'].package) 199*8975f5c5SAndroid Build Coastguard Worker _WipeUnderDirIfMatch(device, '/data/app-lib/', _CHROME_PACKAGE_REGEX) 200*8975f5c5SAndroid Build Coastguard Worker _WipeUnderDirIfMatch(device, '/data/tombstones/', _TOMBSTONE_REGEX) 201*8975f5c5SAndroid Build Coastguard Worker 202*8975f5c5SAndroid Build Coastguard Worker _WipeFileOrDir(device, '/data/local.prop') 203*8975f5c5SAndroid Build Coastguard Worker _WipeFileOrDir(device, '/data/local/chrome-command-line') 204*8975f5c5SAndroid Build Coastguard Worker _WipeFileOrDir(device, '/data/local/.config/') 205*8975f5c5SAndroid Build Coastguard Worker _WipeFileOrDir(device, '/data/local/tmp/') 206*8975f5c5SAndroid Build Coastguard Worker device.RunShellCommand('rm -rf %s/*' % device.GetExternalStoragePath(), 207*8975f5c5SAndroid Build Coastguard Worker check_return=True) 208*8975f5c5SAndroid Build Coastguard Worker except device_errors.CommandFailedError: 209*8975f5c5SAndroid Build Coastguard Worker logging.exception('Possible failure while wiping the device. ' 210*8975f5c5SAndroid Build Coastguard Worker 'Attempting to continue.') 211*8975f5c5SAndroid Build Coastguard Worker 212*8975f5c5SAndroid Build Coastguard Worker 213*8975f5c5SAndroid Build Coastguard Workerdef WipeDevice(device, options): 214*8975f5c5SAndroid Build Coastguard Worker """Wipes data from device, keeping only the adb_keys for authorization. 215*8975f5c5SAndroid Build Coastguard Worker 216*8975f5c5SAndroid Build Coastguard Worker After wiping data on a device that has been authorized, adb can still 217*8975f5c5SAndroid Build Coastguard Worker communicate with the device, but after reboot the device will need to be 218*8975f5c5SAndroid Build Coastguard Worker re-authorized because the adb keys file is stored in /data/misc/adb/. 219*8975f5c5SAndroid Build Coastguard Worker Thus, adb_keys file is rewritten so the device does not need to be 220*8975f5c5SAndroid Build Coastguard Worker re-authorized. 221*8975f5c5SAndroid Build Coastguard Worker 222*8975f5c5SAndroid Build Coastguard Worker Arguments: 223*8975f5c5SAndroid Build Coastguard Worker device: the device to wipe 224*8975f5c5SAndroid Build Coastguard Worker """ 225*8975f5c5SAndroid Build Coastguard Worker if options.skip_wipe: 226*8975f5c5SAndroid Build Coastguard Worker return 227*8975f5c5SAndroid Build Coastguard Worker 228*8975f5c5SAndroid Build Coastguard Worker try: 229*8975f5c5SAndroid Build Coastguard Worker device.EnableRoot() 230*8975f5c5SAndroid Build Coastguard Worker device_authorized = device.FileExists(constants.ADB_KEYS_FILE) 231*8975f5c5SAndroid Build Coastguard Worker if device_authorized: 232*8975f5c5SAndroid Build Coastguard Worker adb_keys = device.ReadFile(constants.ADB_KEYS_FILE, 233*8975f5c5SAndroid Build Coastguard Worker as_root=True).splitlines() 234*8975f5c5SAndroid Build Coastguard Worker device.RunShellCommand(['wipe', 'data'], 235*8975f5c5SAndroid Build Coastguard Worker as_root=True, check_return=True) 236*8975f5c5SAndroid Build Coastguard Worker device.adb.WaitForDevice() 237*8975f5c5SAndroid Build Coastguard Worker 238*8975f5c5SAndroid Build Coastguard Worker if device_authorized: 239*8975f5c5SAndroid Build Coastguard Worker adb_keys_set = set(adb_keys) 240*8975f5c5SAndroid Build Coastguard Worker for adb_key_file in options.adb_key_files or []: 241*8975f5c5SAndroid Build Coastguard Worker try: 242*8975f5c5SAndroid Build Coastguard Worker with open(adb_key_file, 'r') as f: 243*8975f5c5SAndroid Build Coastguard Worker adb_public_keys = f.readlines() 244*8975f5c5SAndroid Build Coastguard Worker adb_keys_set.update(adb_public_keys) 245*8975f5c5SAndroid Build Coastguard Worker except IOError: 246*8975f5c5SAndroid Build Coastguard Worker logging.warning('Unable to find adb keys file %s.', adb_key_file) 247*8975f5c5SAndroid Build Coastguard Worker _WriteAdbKeysFile(device, '\n'.join(adb_keys_set)) 248*8975f5c5SAndroid Build Coastguard Worker except device_errors.CommandFailedError: 249*8975f5c5SAndroid Build Coastguard Worker logging.exception('Possible failure while wiping the device. ' 250*8975f5c5SAndroid Build Coastguard Worker 'Attempting to continue.') 251*8975f5c5SAndroid Build Coastguard Worker 252*8975f5c5SAndroid Build Coastguard Worker 253*8975f5c5SAndroid Build Coastguard Workerdef _WriteAdbKeysFile(device, adb_keys_string): 254*8975f5c5SAndroid Build Coastguard Worker dir_path = posixpath.dirname(constants.ADB_KEYS_FILE) 255*8975f5c5SAndroid Build Coastguard Worker device.RunShellCommand(['mkdir', '-p', dir_path], 256*8975f5c5SAndroid Build Coastguard Worker as_root=True, check_return=True) 257*8975f5c5SAndroid Build Coastguard Worker device.RunShellCommand(['restorecon', dir_path], 258*8975f5c5SAndroid Build Coastguard Worker as_root=True, check_return=True) 259*8975f5c5SAndroid Build Coastguard Worker device.WriteFile(constants.ADB_KEYS_FILE, adb_keys_string, as_root=True) 260*8975f5c5SAndroid Build Coastguard Worker device.RunShellCommand(['restorecon', constants.ADB_KEYS_FILE], 261*8975f5c5SAndroid Build Coastguard Worker as_root=True, check_return=True) 262*8975f5c5SAndroid Build Coastguard Worker 263*8975f5c5SAndroid Build Coastguard Worker 264*8975f5c5SAndroid Build Coastguard Workerdef SetProperties(device, options): 265*8975f5c5SAndroid Build Coastguard Worker try: 266*8975f5c5SAndroid Build Coastguard Worker device.EnableRoot() 267*8975f5c5SAndroid Build Coastguard Worker except device_errors.CommandFailedError as e: 268*8975f5c5SAndroid Build Coastguard Worker logging.warning(str(e)) 269*8975f5c5SAndroid Build Coastguard Worker 270*8975f5c5SAndroid Build Coastguard Worker if not device.IsUserBuild(): 271*8975f5c5SAndroid Build Coastguard Worker _ConfigureLocalProperties(device, options.enable_java_debug) 272*8975f5c5SAndroid Build Coastguard Worker else: 273*8975f5c5SAndroid Build Coastguard Worker logging.warning('Cannot configure properties in user builds.') 274*8975f5c5SAndroid Build Coastguard Worker device_settings.ConfigureContentSettings( 275*8975f5c5SAndroid Build Coastguard Worker device, device_settings.DETERMINISTIC_DEVICE_SETTINGS) 276*8975f5c5SAndroid Build Coastguard Worker if options.disable_location: 277*8975f5c5SAndroid Build Coastguard Worker device_settings.ConfigureContentSettings( 278*8975f5c5SAndroid Build Coastguard Worker device, device_settings.DISABLE_LOCATION_SETTINGS) 279*8975f5c5SAndroid Build Coastguard Worker else: 280*8975f5c5SAndroid Build Coastguard Worker device_settings.ConfigureContentSettings( 281*8975f5c5SAndroid Build Coastguard Worker device, device_settings.ENABLE_LOCATION_SETTINGS) 282*8975f5c5SAndroid Build Coastguard Worker 283*8975f5c5SAndroid Build Coastguard Worker if options.disable_mock_location: 284*8975f5c5SAndroid Build Coastguard Worker device_settings.ConfigureContentSettings( 285*8975f5c5SAndroid Build Coastguard Worker device, device_settings.DISABLE_MOCK_LOCATION_SETTINGS) 286*8975f5c5SAndroid Build Coastguard Worker else: 287*8975f5c5SAndroid Build Coastguard Worker device_settings.ConfigureContentSettings( 288*8975f5c5SAndroid Build Coastguard Worker device, device_settings.ENABLE_MOCK_LOCATION_SETTINGS) 289*8975f5c5SAndroid Build Coastguard Worker 290*8975f5c5SAndroid Build Coastguard Worker device_settings.SetLockScreenSettings(device) 291*8975f5c5SAndroid Build Coastguard Worker if options.disable_network: 292*8975f5c5SAndroid Build Coastguard Worker device_settings.ConfigureContentSettings( 293*8975f5c5SAndroid Build Coastguard Worker device, device_settings.NETWORK_DISABLED_SETTINGS) 294*8975f5c5SAndroid Build Coastguard Worker if device.build_version_sdk >= version_codes.MARSHMALLOW: 295*8975f5c5SAndroid Build Coastguard Worker # Ensure that NFC is also switched off. 296*8975f5c5SAndroid Build Coastguard Worker device.RunShellCommand(['svc', 'nfc', 'disable'], 297*8975f5c5SAndroid Build Coastguard Worker as_root=True, check_return=True) 298*8975f5c5SAndroid Build Coastguard Worker 299*8975f5c5SAndroid Build Coastguard Worker if options.disable_system_chrome: 300*8975f5c5SAndroid Build Coastguard Worker # The system chrome version on the device interferes with some tests. 301*8975f5c5SAndroid Build Coastguard Worker device.RunShellCommand(['pm', 'disable', 'com.android.chrome'], 302*8975f5c5SAndroid Build Coastguard Worker check_return=True) 303*8975f5c5SAndroid Build Coastguard Worker 304*8975f5c5SAndroid Build Coastguard Worker if options.remove_system_webview: 305*8975f5c5SAndroid Build Coastguard Worker if any(device.PathExists(p) for p in _SYSTEM_WEBVIEW_PATHS): 306*8975f5c5SAndroid Build Coastguard Worker logging.info('System WebView exists and needs to be removed') 307*8975f5c5SAndroid Build Coastguard Worker if device.HasRoot(): 308*8975f5c5SAndroid Build Coastguard Worker # Disabled Marshmallow's Verity security feature 309*8975f5c5SAndroid Build Coastguard Worker if device.build_version_sdk >= version_codes.MARSHMALLOW: 310*8975f5c5SAndroid Build Coastguard Worker device.adb.DisableVerity() 311*8975f5c5SAndroid Build Coastguard Worker device.Reboot() 312*8975f5c5SAndroid Build Coastguard Worker device.WaitUntilFullyBooted() 313*8975f5c5SAndroid Build Coastguard Worker device.EnableRoot() 314*8975f5c5SAndroid Build Coastguard Worker 315*8975f5c5SAndroid Build Coastguard Worker # This is required, e.g., to replace the system webview on a device. 316*8975f5c5SAndroid Build Coastguard Worker device.adb.Remount() 317*8975f5c5SAndroid Build Coastguard Worker device.RunShellCommand(['stop'], check_return=True) 318*8975f5c5SAndroid Build Coastguard Worker device.RunShellCommand(['rm', '-rf'] + _SYSTEM_WEBVIEW_PATHS, 319*8975f5c5SAndroid Build Coastguard Worker check_return=True) 320*8975f5c5SAndroid Build Coastguard Worker device.RunShellCommand(['start'], check_return=True) 321*8975f5c5SAndroid Build Coastguard Worker else: 322*8975f5c5SAndroid Build Coastguard Worker logging.warning('Cannot remove system webview from a non-rooted device') 323*8975f5c5SAndroid Build Coastguard Worker else: 324*8975f5c5SAndroid Build Coastguard Worker logging.info('System WebView already removed') 325*8975f5c5SAndroid Build Coastguard Worker 326*8975f5c5SAndroid Build Coastguard Worker # Some device types can momentarily disappear after setting properties. 327*8975f5c5SAndroid Build Coastguard Worker device.adb.WaitForDevice() 328*8975f5c5SAndroid Build Coastguard Worker 329*8975f5c5SAndroid Build Coastguard Worker 330*8975f5c5SAndroid Build Coastguard Workerdef _ConfigureLocalProperties(device, java_debug=True): 331*8975f5c5SAndroid Build Coastguard Worker """Set standard readonly testing device properties prior to reboot.""" 332*8975f5c5SAndroid Build Coastguard Worker local_props = [ 333*8975f5c5SAndroid Build Coastguard Worker 'persist.sys.usb.config=adb', 334*8975f5c5SAndroid Build Coastguard Worker 'ro.monkey=1', 335*8975f5c5SAndroid Build Coastguard Worker 'ro.test_harness=1', 336*8975f5c5SAndroid Build Coastguard Worker 'ro.audio.silent=1', 337*8975f5c5SAndroid Build Coastguard Worker 'ro.setupwizard.mode=DISABLED', 338*8975f5c5SAndroid Build Coastguard Worker ] 339*8975f5c5SAndroid Build Coastguard Worker if java_debug: 340*8975f5c5SAndroid Build Coastguard Worker local_props.append( 341*8975f5c5SAndroid Build Coastguard Worker '%s=all' % device_utils.DeviceUtils.JAVA_ASSERT_PROPERTY) 342*8975f5c5SAndroid Build Coastguard Worker local_props.append('debug.checkjni=1') 343*8975f5c5SAndroid Build Coastguard Worker try: 344*8975f5c5SAndroid Build Coastguard Worker device.WriteFile( 345*8975f5c5SAndroid Build Coastguard Worker device.LOCAL_PROPERTIES_PATH, 346*8975f5c5SAndroid Build Coastguard Worker '\n'.join(local_props), as_root=True) 347*8975f5c5SAndroid Build Coastguard Worker # Android will not respect the local props file if it is world writable. 348*8975f5c5SAndroid Build Coastguard Worker device.RunShellCommand( 349*8975f5c5SAndroid Build Coastguard Worker ['chmod', '644', device.LOCAL_PROPERTIES_PATH], 350*8975f5c5SAndroid Build Coastguard Worker as_root=True, check_return=True) 351*8975f5c5SAndroid Build Coastguard Worker except device_errors.CommandFailedError: 352*8975f5c5SAndroid Build Coastguard Worker logging.exception('Failed to configure local properties.') 353*8975f5c5SAndroid Build Coastguard Worker 354*8975f5c5SAndroid Build Coastguard Worker 355*8975f5c5SAndroid Build Coastguard Workerdef FinishProvisioning(device, options): 356*8975f5c5SAndroid Build Coastguard Worker # The lockscreen can't be disabled on user builds, so send a keyevent 357*8975f5c5SAndroid Build Coastguard Worker # to unlock it. 358*8975f5c5SAndroid Build Coastguard Worker if device.IsUserBuild(): 359*8975f5c5SAndroid Build Coastguard Worker device.SendKeyEvent(keyevent.KEYCODE_MENU) 360*8975f5c5SAndroid Build Coastguard Worker 361*8975f5c5SAndroid Build Coastguard Worker if options.min_battery_level is not None: 362*8975f5c5SAndroid Build Coastguard Worker battery = battery_utils.BatteryUtils(device) 363*8975f5c5SAndroid Build Coastguard Worker try: 364*8975f5c5SAndroid Build Coastguard Worker battery.ChargeDeviceToLevel(options.min_battery_level) 365*8975f5c5SAndroid Build Coastguard Worker except device_errors.DeviceChargingError: 366*8975f5c5SAndroid Build Coastguard Worker device.Reboot() 367*8975f5c5SAndroid Build Coastguard Worker battery.ChargeDeviceToLevel(options.min_battery_level) 368*8975f5c5SAndroid Build Coastguard Worker 369*8975f5c5SAndroid Build Coastguard Worker if options.max_battery_temp is not None: 370*8975f5c5SAndroid Build Coastguard Worker try: 371*8975f5c5SAndroid Build Coastguard Worker battery = battery_utils.BatteryUtils(device) 372*8975f5c5SAndroid Build Coastguard Worker battery.LetBatteryCoolToTemperature(options.max_battery_temp) 373*8975f5c5SAndroid Build Coastguard Worker except device_errors.CommandFailedError: 374*8975f5c5SAndroid Build Coastguard Worker logging.exception('Unable to let battery cool to specified temperature.') 375*8975f5c5SAndroid Build Coastguard Worker 376*8975f5c5SAndroid Build Coastguard Worker def _set_and_verify_date(): 377*8975f5c5SAndroid Build Coastguard Worker if device.build_version_sdk >= version_codes.MARSHMALLOW: 378*8975f5c5SAndroid Build Coastguard Worker date_format = '%m%d%H%M%Y.%S' 379*8975f5c5SAndroid Build Coastguard Worker set_date_command = ['date', '-u'] 380*8975f5c5SAndroid Build Coastguard Worker get_date_command = ['date', '-u'] 381*8975f5c5SAndroid Build Coastguard Worker else: 382*8975f5c5SAndroid Build Coastguard Worker date_format = '%Y%m%d.%H%M%S' 383*8975f5c5SAndroid Build Coastguard Worker set_date_command = ['date', '-s'] 384*8975f5c5SAndroid Build Coastguard Worker get_date_command = ['date'] 385*8975f5c5SAndroid Build Coastguard Worker 386*8975f5c5SAndroid Build Coastguard Worker # TODO(jbudorick): This is wrong on pre-M devices -- get/set are 387*8975f5c5SAndroid Build Coastguard Worker # dealing in local time, but we're setting based on GMT. 388*8975f5c5SAndroid Build Coastguard Worker strgmtime = time.strftime(date_format, time.gmtime()) 389*8975f5c5SAndroid Build Coastguard Worker set_date_command.append(strgmtime) 390*8975f5c5SAndroid Build Coastguard Worker device.RunShellCommand(set_date_command, as_root=True, check_return=True) 391*8975f5c5SAndroid Build Coastguard Worker 392*8975f5c5SAndroid Build Coastguard Worker get_date_command.append('+"%Y%m%d.%H%M%S"') 393*8975f5c5SAndroid Build Coastguard Worker device_time = device.RunShellCommand( 394*8975f5c5SAndroid Build Coastguard Worker get_date_command, as_root=True, single_line=True).replace('"', '') 395*8975f5c5SAndroid Build Coastguard Worker device_time = datetime.datetime.strptime(device_time, "%Y%m%d.%H%M%S") 396*8975f5c5SAndroid Build Coastguard Worker correct_time = datetime.datetime.strptime(strgmtime, date_format) 397*8975f5c5SAndroid Build Coastguard Worker tdelta = abs(correct_time - device_time).seconds 398*8975f5c5SAndroid Build Coastguard Worker if tdelta <= 1: 399*8975f5c5SAndroid Build Coastguard Worker logging.info('Date/time successfully set on %s', device) 400*8975f5c5SAndroid Build Coastguard Worker return True 401*8975f5c5SAndroid Build Coastguard Worker logging.error('Date mismatch. Device: %s Correct: %s', 402*8975f5c5SAndroid Build Coastguard Worker device_time.isoformat(), correct_time.isoformat()) 403*8975f5c5SAndroid Build Coastguard Worker return False 404*8975f5c5SAndroid Build Coastguard Worker 405*8975f5c5SAndroid Build Coastguard Worker # Sometimes the date is not set correctly on the devices. Retry on failure. 406*8975f5c5SAndroid Build Coastguard Worker if device.IsUserBuild(): 407*8975f5c5SAndroid Build Coastguard Worker # TODO(bpastene): Figure out how to set the date & time on user builds. 408*8975f5c5SAndroid Build Coastguard Worker pass 409*8975f5c5SAndroid Build Coastguard Worker else: 410*8975f5c5SAndroid Build Coastguard Worker if not timeout_retry.WaitFor( 411*8975f5c5SAndroid Build Coastguard Worker _set_and_verify_date, wait_period=1, max_tries=2): 412*8975f5c5SAndroid Build Coastguard Worker raise device_errors.CommandFailedError( 413*8975f5c5SAndroid Build Coastguard Worker 'Failed to set date & time.', device_serial=str(device)) 414*8975f5c5SAndroid Build Coastguard Worker 415*8975f5c5SAndroid Build Coastguard Worker props = device.RunShellCommand('getprop', check_return=True) 416*8975f5c5SAndroid Build Coastguard Worker for prop in props: 417*8975f5c5SAndroid Build Coastguard Worker logging.info(' %s', prop) 418*8975f5c5SAndroid Build Coastguard Worker if options.auto_reconnect: 419*8975f5c5SAndroid Build Coastguard Worker _PushAndLaunchAdbReboot(device, options.target) 420*8975f5c5SAndroid Build Coastguard Worker 421*8975f5c5SAndroid Build Coastguard Worker 422*8975f5c5SAndroid Build Coastguard Workerdef _UninstallIfMatch(device, pattern, app_to_keep): 423*8975f5c5SAndroid Build Coastguard Worker installed_packages = device.RunShellCommand(['pm', 'list', 'packages']) 424*8975f5c5SAndroid Build Coastguard Worker installed_system_packages = [ 425*8975f5c5SAndroid Build Coastguard Worker pkg.split(':')[1] for pkg in device.RunShellCommand(['pm', 'list', 426*8975f5c5SAndroid Build Coastguard Worker 'packages', '-s'])] 427*8975f5c5SAndroid Build Coastguard Worker for package_output in installed_packages: 428*8975f5c5SAndroid Build Coastguard Worker package = package_output.split(":")[1] 429*8975f5c5SAndroid Build Coastguard Worker if pattern.match(package) and not package == app_to_keep: 430*8975f5c5SAndroid Build Coastguard Worker if not device.IsUserBuild() or package not in installed_system_packages: 431*8975f5c5SAndroid Build Coastguard Worker device.Uninstall(package) 432*8975f5c5SAndroid Build Coastguard Worker 433*8975f5c5SAndroid Build Coastguard Worker 434*8975f5c5SAndroid Build Coastguard Workerdef _WipeUnderDirIfMatch(device, path, pattern): 435*8975f5c5SAndroid Build Coastguard Worker for filename in device.ListDirectory(path): 436*8975f5c5SAndroid Build Coastguard Worker if pattern.match(filename): 437*8975f5c5SAndroid Build Coastguard Worker _WipeFileOrDir(device, posixpath.join(path, filename)) 438*8975f5c5SAndroid Build Coastguard Worker 439*8975f5c5SAndroid Build Coastguard Worker 440*8975f5c5SAndroid Build Coastguard Workerdef _WipeFileOrDir(device, path): 441*8975f5c5SAndroid Build Coastguard Worker if device.PathExists(path): 442*8975f5c5SAndroid Build Coastguard Worker device.RunShellCommand(['rm', '-rf', path], check_return=True) 443*8975f5c5SAndroid Build Coastguard Worker 444*8975f5c5SAndroid Build Coastguard Worker 445*8975f5c5SAndroid Build Coastguard Workerdef _PushAndLaunchAdbReboot(device, target): 446*8975f5c5SAndroid Build Coastguard Worker """Pushes and launches the adb_reboot binary on the device. 447*8975f5c5SAndroid Build Coastguard Worker 448*8975f5c5SAndroid Build Coastguard Worker Arguments: 449*8975f5c5SAndroid Build Coastguard Worker device: The DeviceUtils instance for the device to which the adb_reboot 450*8975f5c5SAndroid Build Coastguard Worker binary should be pushed. 451*8975f5c5SAndroid Build Coastguard Worker target: The build target (example, Debug or Release) which helps in 452*8975f5c5SAndroid Build Coastguard Worker locating the adb_reboot binary. 453*8975f5c5SAndroid Build Coastguard Worker """ 454*8975f5c5SAndroid Build Coastguard Worker logging.info('Will push and launch adb_reboot on %s', str(device)) 455*8975f5c5SAndroid Build Coastguard Worker # Kill if adb_reboot is already running. 456*8975f5c5SAndroid Build Coastguard Worker device.KillAll('adb_reboot', blocking=True, timeout=2, quiet=True) 457*8975f5c5SAndroid Build Coastguard Worker # Push adb_reboot 458*8975f5c5SAndroid Build Coastguard Worker logging.info(' Pushing adb_reboot ...') 459*8975f5c5SAndroid Build Coastguard Worker adb_reboot = os.path.join(host_paths.DIR_SOURCE_ROOT, 460*8975f5c5SAndroid Build Coastguard Worker 'out/%s/adb_reboot' % target) 461*8975f5c5SAndroid Build Coastguard Worker device.PushChangedFiles([(adb_reboot, '/data/local/tmp/')]) 462*8975f5c5SAndroid Build Coastguard Worker # Launch adb_reboot 463*8975f5c5SAndroid Build Coastguard Worker logging.info(' Launching adb_reboot ...') 464*8975f5c5SAndroid Build Coastguard Worker device.RunShellCommand( 465*8975f5c5SAndroid Build Coastguard Worker ['/data/local/tmp/adb_reboot'], 466*8975f5c5SAndroid Build Coastguard Worker check_return=True) 467*8975f5c5SAndroid Build Coastguard Worker 468*8975f5c5SAndroid Build Coastguard Worker 469*8975f5c5SAndroid Build Coastguard Workerdef _LaunchHostHeartbeat(): 470*8975f5c5SAndroid Build Coastguard Worker # Kill if existing host_heartbeat 471*8975f5c5SAndroid Build Coastguard Worker KillHostHeartbeat() 472*8975f5c5SAndroid Build Coastguard Worker # Launch a new host_heartbeat 473*8975f5c5SAndroid Build Coastguard Worker logging.info('Spawning host heartbeat...') 474*8975f5c5SAndroid Build Coastguard Worker subprocess.Popen([os.path.join(host_paths.DIR_SOURCE_ROOT, 475*8975f5c5SAndroid Build Coastguard Worker 'build/android/host_heartbeat.py')]) 476*8975f5c5SAndroid Build Coastguard Worker 477*8975f5c5SAndroid Build Coastguard Workerdef KillHostHeartbeat(): 478*8975f5c5SAndroid Build Coastguard Worker ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE) 479*8975f5c5SAndroid Build Coastguard Worker stdout, _ = ps.communicate() 480*8975f5c5SAndroid Build Coastguard Worker matches = re.findall('\\n.*host_heartbeat.*', stdout) 481*8975f5c5SAndroid Build Coastguard Worker for match in matches: 482*8975f5c5SAndroid Build Coastguard Worker logging.info('An instance of host heart beart running... will kill') 483*8975f5c5SAndroid Build Coastguard Worker pid = re.findall(r'(\S+)', match)[1] 484*8975f5c5SAndroid Build Coastguard Worker subprocess.call(['kill', str(pid)]) 485*8975f5c5SAndroid Build Coastguard Worker 486*8975f5c5SAndroid Build Coastguard Workerdef main(): 487*8975f5c5SAndroid Build Coastguard Worker # Recommended options on perf bots: 488*8975f5c5SAndroid Build Coastguard Worker # --disable-network 489*8975f5c5SAndroid Build Coastguard Worker # TODO(tonyg): We eventually want network on. However, currently radios 490*8975f5c5SAndroid Build Coastguard Worker # can cause perfbots to drain faster than they charge. 491*8975f5c5SAndroid Build Coastguard Worker # --min-battery-level 95 492*8975f5c5SAndroid Build Coastguard Worker # Some perf bots run benchmarks with USB charging disabled which leads 493*8975f5c5SAndroid Build Coastguard Worker # to gradual draining of the battery. We must wait for a full charge 494*8975f5c5SAndroid Build Coastguard Worker # before starting a run in order to keep the devices online. 495*8975f5c5SAndroid Build Coastguard Worker 496*8975f5c5SAndroid Build Coastguard Worker parser = argparse.ArgumentParser( 497*8975f5c5SAndroid Build Coastguard Worker description='Provision Android devices with settings required for bots.') 498*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('-d', '--device', metavar='SERIAL', 499*8975f5c5SAndroid Build Coastguard Worker help='the serial number of the device to be provisioned' 500*8975f5c5SAndroid Build Coastguard Worker ' (the default is to provision all devices attached)') 501*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--adb-path', 502*8975f5c5SAndroid Build Coastguard Worker help='Absolute path to the adb binary to use.') 503*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--denylist-file', help='Device denylist JSON file.') 504*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--phase', action='append', choices=_PHASES.ALL, 505*8975f5c5SAndroid Build Coastguard Worker dest='phases', 506*8975f5c5SAndroid Build Coastguard Worker help='Phases of provisioning to run. ' 507*8975f5c5SAndroid Build Coastguard Worker '(If omitted, all phases will be run.)') 508*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--skip-wipe', action='store_true', default=False, 509*8975f5c5SAndroid Build Coastguard Worker help="don't wipe device data during provisioning") 510*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--reboot-timeout', metavar='SECS', type=int, 511*8975f5c5SAndroid Build Coastguard Worker help='when wiping the device, max number of seconds to' 512*8975f5c5SAndroid Build Coastguard Worker ' wait after each reboot ' 513*8975f5c5SAndroid Build Coastguard Worker '(default: %s)' % _DEFAULT_TIMEOUTS.HELP_TEXT) 514*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--min-battery-level', type=int, metavar='NUM', 515*8975f5c5SAndroid Build Coastguard Worker help='wait for the device to reach this minimum battery' 516*8975f5c5SAndroid Build Coastguard Worker ' level before trying to continue') 517*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--disable-location', action='store_true', 518*8975f5c5SAndroid Build Coastguard Worker help='disable Google location services on devices') 519*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--disable-mock-location', action='store_true', 520*8975f5c5SAndroid Build Coastguard Worker default=False, help='Set ALLOW_MOCK_LOCATION to false') 521*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--disable-network', action='store_true', 522*8975f5c5SAndroid Build Coastguard Worker help='disable network access on devices') 523*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--disable-java-debug', action='store_false', 524*8975f5c5SAndroid Build Coastguard Worker dest='enable_java_debug', default=True, 525*8975f5c5SAndroid Build Coastguard Worker help='disable Java property asserts and JNI checking') 526*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--disable-system-chrome', action='store_true', 527*8975f5c5SAndroid Build Coastguard Worker help='Disable the system chrome from devices.') 528*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--remove-system-webview', action='store_true', 529*8975f5c5SAndroid Build Coastguard Worker help='Remove the system webview from devices.') 530*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('-t', '--target', default='Debug', 531*8975f5c5SAndroid Build Coastguard Worker help='the build target (default: %(default)s)') 532*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('-r', '--auto-reconnect', action='store_true', 533*8975f5c5SAndroid Build Coastguard Worker help='push binary which will reboot the device on adb' 534*8975f5c5SAndroid Build Coastguard Worker ' disconnections') 535*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--adb-key-files', type=str, nargs='+', 536*8975f5c5SAndroid Build Coastguard Worker help='list of adb keys to push to device') 537*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('-v', '--verbose', action='count', default=1, 538*8975f5c5SAndroid Build Coastguard Worker help='Log more information.') 539*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--max-battery-temp', type=int, metavar='NUM', 540*8975f5c5SAndroid Build Coastguard Worker help='Wait for the battery to have this temp or lower.') 541*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--output-device-denylist', 542*8975f5c5SAndroid Build Coastguard Worker help='Json file to output the device denylist.') 543*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--chrome-specific-wipe', action='store_true', 544*8975f5c5SAndroid Build Coastguard Worker help='only wipe chrome specific data during provisioning') 545*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--emulators', action='store_true', 546*8975f5c5SAndroid Build Coastguard Worker help='provision only emulators and ignore usb devices') 547*8975f5c5SAndroid Build Coastguard Worker args = parser.parse_args() 548*8975f5c5SAndroid Build Coastguard Worker constants.SetBuildType(args.target) 549*8975f5c5SAndroid Build Coastguard Worker 550*8975f5c5SAndroid Build Coastguard Worker run_tests_helper.SetLogLevel(args.verbose) 551*8975f5c5SAndroid Build Coastguard Worker 552*8975f5c5SAndroid Build Coastguard Worker devil_chromium.Initialize(adb_path=args.adb_path) 553*8975f5c5SAndroid Build Coastguard Worker 554*8975f5c5SAndroid Build Coastguard Worker try: 555*8975f5c5SAndroid Build Coastguard Worker return ProvisionDevices(args) 556*8975f5c5SAndroid Build Coastguard Worker except (device_errors.DeviceUnreachableError, device_errors.NoDevicesError): 557*8975f5c5SAndroid Build Coastguard Worker logging.exception('Unable to provision local devices.') 558*8975f5c5SAndroid Build Coastguard Worker return exit_codes.INFRA 559*8975f5c5SAndroid Build Coastguard Worker 560*8975f5c5SAndroid Build Coastguard Worker 561*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__': 562*8975f5c5SAndroid Build Coastguard Worker sys.exit(main()) 563