Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # | 2 # |
| 3 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | 3 # Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 """Provisions Android devices with settings required for bots. | 7 """Provisions Android devices with settings required for bots. |
| 8 | 8 |
| 9 Usage: | 9 Usage: |
| 10 ./provision_devices.py [-d <device serial number>] | 10 ./provision_devices.py [-d <device serial number>] |
| 11 """ | 11 """ |
| 12 | 12 |
| 13 import argparse | 13 import argparse |
| 14 import datetime | 14 import datetime |
| 15 import json | 15 import json |
| 16 import logging | 16 import logging |
| 17 import os | 17 import os |
| 18 import posixpath | 18 import posixpath |
| 19 import re | 19 import re |
| 20 import subprocess | 20 import subprocess |
| 21 import sys | 21 import sys |
| 22 import time | 22 import time |
| 23 | 23 |
| 24 from devil.android import battery_utils | 24 from devil.android import battery_utils |
| 25 from devil.android import device_blacklist | 25 from devil.android import device_blacklist |
| 26 from devil.android import device_errors | 26 from devil.android import device_errors |
| 27 from devil.android import device_temp_file | 27 from devil.android import device_temp_file |
| 28 from devil.android import device_utils | 28 from devil.android import device_utils |
| 29 from devil.android.sdk import keyevent | |
| 29 from devil.android.sdk import version_codes | 30 from devil.android.sdk import version_codes |
| 30 from devil.utils import run_tests_helper | 31 from devil.utils import run_tests_helper |
| 31 from devil.utils import timeout_retry | 32 from devil.utils import timeout_retry |
| 32 from pylib import constants | 33 from pylib import constants |
| 33 from pylib import device_settings | 34 from pylib import device_settings |
| 34 | 35 |
| 35 _SYSTEM_WEBVIEW_PATHS = ['/system/app/webview', '/system/app/WebViewGoogle'] | 36 _SYSTEM_WEBVIEW_PATHS = ['/system/app/webview', '/system/app/WebViewGoogle'] |
| 36 _CHROME_PACKAGE_REGEX = re.compile('.*chrom.*') | 37 _CHROME_PACKAGE_REGEX = re.compile('.*chrom.*') |
| 37 _TOMBSTONE_REGEX = re.compile('tombstone.*') | 38 _TOMBSTONE_REGEX = re.compile('tombstone.*') |
| 38 | 39 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 99 phase_func(device, options) | 100 phase_func(device, options) |
| 100 if reboot: | 101 if reboot: |
| 101 device.Reboot(False, retries=0) | 102 device.Reboot(False, retries=0) |
| 102 device.adb.WaitForDevice() | 103 device.adb.WaitForDevice() |
| 103 | 104 |
| 104 try: | 105 try: |
| 105 if should_run_phase(_PHASES.WIPE): | 106 if should_run_phase(_PHASES.WIPE): |
| 106 if options.chrome_specific_wipe: | 107 if options.chrome_specific_wipe: |
| 107 run_phase(WipeChromeData) | 108 run_phase(WipeChromeData) |
| 108 else: | 109 else: |
| 109 run_phase(WipeDevice) | 110 if device.IsUserBuild(): |
|
jbudorick
2015/12/09 18:09:01
We should just do the chrome-specific wipe on user
bpastene
2015/12/09 18:59:13
Was planning on setting non_device_wipe_provisioni
| |
| 111 logging.warning('Cannot wipe data in user builds.') | |
| 112 else: | |
| 113 run_phase(WipeDevice) | |
| 110 | 114 |
| 111 if should_run_phase(_PHASES.PROPERTIES): | 115 if should_run_phase(_PHASES.PROPERTIES): |
| 112 run_phase(SetProperties) | 116 run_phase(SetProperties) |
| 113 | 117 |
| 114 if should_run_phase(_PHASES.FINISH): | 118 if should_run_phase(_PHASES.FINISH): |
| 115 run_phase(FinishProvisioning, reboot=False) | 119 run_phase(FinishProvisioning, reboot=False) |
| 116 | 120 |
| 117 if options.chrome_specific_wipe: | 121 if options.chrome_specific_wipe: |
| 118 package = "com.google.android.gms" | 122 package = "com.google.android.gms" |
| 119 version_name = device.GetApplicationVersion(package) | 123 version_name = device.GetApplicationVersion(package) |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 164 (this is telemetry related) | 168 (this is telemetry related) |
| 165 (7) remove anything under /data/local/tmp/ | 169 (7) remove anything under /data/local/tmp/ |
| 166 | 170 |
| 167 Arguments: | 171 Arguments: |
| 168 device: the device to wipe | 172 device: the device to wipe |
| 169 """ | 173 """ |
| 170 if options.skip_wipe: | 174 if options.skip_wipe: |
| 171 return | 175 return |
| 172 | 176 |
| 173 try: | 177 try: |
| 174 device.EnableRoot() | 178 if device.IsUserBuild(): |
| 175 _UninstallIfMatch(device, _CHROME_PACKAGE_REGEX, | 179 _UninstallIfMatch(device, _CHROME_PACKAGE_REGEX, |
| 176 constants.PACKAGE_INFO['chrome_stable'].package) | 180 constants.PACKAGE_INFO['chrome_stable'].package) |
| 177 _WipeUnderDirIfMatch(device, '/data/app-lib/', _CHROME_PACKAGE_REGEX) | 181 device.RunShellCommand('rm -rf %s/*' % device.GetExternalStoragePath(), |
| 178 _WipeUnderDirIfMatch(device, '/data/tombstones/', _TOMBSTONE_REGEX) | 182 check_return=True) |
| 183 else: | |
| 184 device.EnableRoot() | |
| 185 _UninstallIfMatch(device, _CHROME_PACKAGE_REGEX, | |
| 186 constants.PACKAGE_INFO['chrome_stable'].package) | |
| 187 _WipeUnderDirIfMatch(device, '/data/app-lib/', _CHROME_PACKAGE_REGEX) | |
| 188 _WipeUnderDirIfMatch(device, '/data/tombstones/', _TOMBSTONE_REGEX) | |
| 179 | 189 |
| 180 _WipeFileOrDir(device, '/data/local.prop') | 190 _WipeFileOrDir(device, '/data/local.prop') |
| 181 _WipeFileOrDir(device, '/data/local/chrome-command-line') | 191 _WipeFileOrDir(device, '/data/local/chrome-command-line') |
| 182 _WipeFileOrDir(device, '/data/local/.config/') | 192 _WipeFileOrDir(device, '/data/local/.config/') |
| 183 _WipeFileOrDir(device, '/data/local/tmp/') | 193 _WipeFileOrDir(device, '/data/local/tmp/') |
|
jbudorick
2015/12/09 18:09:01
should be able to remove the contents of /data/loc
bpastene
2015/12/09 18:59:13
Good catch
| |
| 184 | 194 device.RunShellCommand('rm -rf %s/*' % device.GetExternalStoragePath(), |
| 185 device.RunShellCommand('rm -rf %s/*' % device.GetExternalStoragePath(), | 195 check_return=True) |
| 186 check_return=True) | |
| 187 except device_errors.CommandFailedError: | 196 except device_errors.CommandFailedError: |
| 188 logging.exception('Possible failure while wiping the device. ' | 197 logging.exception('Possible failure while wiping the device. ' |
| 189 'Attempting to continue.') | 198 'Attempting to continue.') |
| 190 | 199 |
| 191 | 200 |
| 192 def WipeDevice(device, options): | 201 def WipeDevice(device, options): |
| 193 """Wipes data from device, keeping only the adb_keys for authorization. | 202 """Wipes data from device, keeping only the adb_keys for authorization. |
| 194 | 203 |
| 195 After wiping data on a device that has been authorized, adb can still | 204 After wiping data on a device that has been authorized, adb can still |
| 196 communicate with the device, but after reboot the device will need to be | 205 communicate with the device, but after reboot the device will need to be |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 239 device.RunShellCommand(['restorecon', constants.ADB_KEYS_FILE], | 248 device.RunShellCommand(['restorecon', constants.ADB_KEYS_FILE], |
| 240 as_root=True, check_return=True) | 249 as_root=True, check_return=True) |
| 241 | 250 |
| 242 | 251 |
| 243 def SetProperties(device, options): | 252 def SetProperties(device, options): |
| 244 try: | 253 try: |
| 245 device.EnableRoot() | 254 device.EnableRoot() |
| 246 except device_errors.CommandFailedError as e: | 255 except device_errors.CommandFailedError as e: |
| 247 logging.warning(str(e)) | 256 logging.warning(str(e)) |
| 248 | 257 |
| 249 _ConfigureLocalProperties(device, options.enable_java_debug) | 258 if not device.IsUserBuild(): |
| 259 _ConfigureLocalProperties(device, options.enable_java_debug) | |
| 260 else: | |
| 261 logging.warning('Cannot configure properties in user builds.') | |
| 250 device_settings.ConfigureContentSettings( | 262 device_settings.ConfigureContentSettings( |
| 251 device, device_settings.DETERMINISTIC_DEVICE_SETTINGS) | 263 device, device_settings.DETERMINISTIC_DEVICE_SETTINGS) |
| 252 if options.disable_location: | 264 if options.disable_location: |
| 253 device_settings.ConfigureContentSettings( | 265 device_settings.ConfigureContentSettings( |
| 254 device, device_settings.DISABLE_LOCATION_SETTINGS) | 266 device, device_settings.DISABLE_LOCATION_SETTINGS) |
| 255 else: | 267 else: |
| 256 device_settings.ConfigureContentSettings( | 268 device_settings.ConfigureContentSettings( |
| 257 device, device_settings.ENABLE_LOCATION_SETTINGS) | 269 device, device_settings.ENABLE_LOCATION_SETTINGS) |
| 258 | 270 |
| 259 if options.disable_mock_location: | 271 if options.disable_mock_location: |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 304 '\n'.join(local_props), as_root=True) | 316 '\n'.join(local_props), as_root=True) |
| 305 # Android will not respect the local props file if it is world writable. | 317 # Android will not respect the local props file if it is world writable. |
| 306 device.RunShellCommand( | 318 device.RunShellCommand( |
| 307 ['chmod', '644', device.LOCAL_PROPERTIES_PATH], | 319 ['chmod', '644', device.LOCAL_PROPERTIES_PATH], |
| 308 as_root=True, check_return=True) | 320 as_root=True, check_return=True) |
| 309 except device_errors.CommandFailedError: | 321 except device_errors.CommandFailedError: |
| 310 logging.exception('Failed to configure local properties.') | 322 logging.exception('Failed to configure local properties.') |
| 311 | 323 |
| 312 | 324 |
| 313 def FinishProvisioning(device, options): | 325 def FinishProvisioning(device, options): |
| 326 # The lockscreen can't be disabled on user builds, so send a keyevent | |
| 327 # to unlock it. | |
| 328 if device.IsUserBuild(): | |
| 329 device.SendKeyEvent(keyevent.KEYCODE_MENU) | |
| 330 | |
| 314 if options.min_battery_level is not None: | 331 if options.min_battery_level is not None: |
| 315 try: | 332 try: |
| 316 battery = battery_utils.BatteryUtils(device) | 333 battery = battery_utils.BatteryUtils(device) |
| 317 battery.ChargeDeviceToLevel(options.min_battery_level) | 334 battery.ChargeDeviceToLevel(options.min_battery_level) |
| 318 except device_errors.CommandFailedError: | 335 except device_errors.CommandFailedError: |
| 319 logging.exception('Unable to charge device to specified level.') | 336 logging.exception('Unable to charge device to specified level.') |
| 320 | 337 |
| 321 if options.max_battery_temp is not None: | 338 if options.max_battery_temp is not None: |
| 322 try: | 339 try: |
| 323 battery = battery_utils.BatteryUtils(device) | 340 battery = battery_utils.BatteryUtils(device) |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 344 tdelta = (correct_time - device_time).seconds | 361 tdelta = (correct_time - device_time).seconds |
| 345 if tdelta <= 1: | 362 if tdelta <= 1: |
| 346 logging.info('Date/time successfully set on %s', device) | 363 logging.info('Date/time successfully set on %s', device) |
| 347 return True | 364 return True |
| 348 else: | 365 else: |
| 349 logging.error('Date mismatch. Device: %s Correct: %s', | 366 logging.error('Date mismatch. Device: %s Correct: %s', |
| 350 device_time.isoformat(), correct_time.isoformat()) | 367 device_time.isoformat(), correct_time.isoformat()) |
| 351 return False | 368 return False |
| 352 | 369 |
| 353 # Sometimes the date is not set correctly on the devices. Retry on failure. | 370 # Sometimes the date is not set correctly on the devices. Retry on failure. |
| 354 if not timeout_retry.WaitFor(_set_and_verify_date, wait_period=1, | 371 if device.IsUserBuild(): |
| 355 max_tries=2): | 372 # TODO(bpastene): Figure out how to set the date & time on user builds. |
| 356 raise device_errors.CommandFailedError( | 373 pass |
| 357 'Failed to set date & time.', device_serial=str(device)) | 374 else: |
| 375 if not timeout_retry.WaitFor( | |
| 376 _set_and_verify_date, wait_period=1, max_tries=2): | |
| 377 raise device_errors.CommandFailedError( | |
| 378 'Failed to set date & time.', device_serial=str(device)) | |
| 358 | 379 |
| 359 props = device.RunShellCommand('getprop', check_return=True) | 380 props = device.RunShellCommand('getprop', check_return=True) |
| 360 for prop in props: | 381 for prop in props: |
| 361 logging.info(' %s', prop) | 382 logging.info(' %s', prop) |
| 362 if options.auto_reconnect: | 383 if options.auto_reconnect: |
| 363 _PushAndLaunchAdbReboot(device, options.target) | 384 _PushAndLaunchAdbReboot(device, options.target) |
| 364 | 385 |
| 365 | 386 |
| 366 def _UninstallIfMatch(device, pattern, app_to_keep): | 387 def _UninstallIfMatch(device, pattern, app_to_keep): |
| 367 installed_packages = device.RunShellCommand(['pm', 'list', 'packages']) | 388 installed_packages = device.RunShellCommand(['pm', 'list', 'packages']) |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 486 args = parser.parse_args() | 507 args = parser.parse_args() |
| 487 constants.SetBuildType(args.target) | 508 constants.SetBuildType(args.target) |
| 488 | 509 |
| 489 run_tests_helper.SetLogLevel(args.verbose) | 510 run_tests_helper.SetLogLevel(args.verbose) |
| 490 | 511 |
| 491 return ProvisionDevices(args) | 512 return ProvisionDevices(args) |
| 492 | 513 |
| 493 | 514 |
| 494 if __name__ == '__main__': | 515 if __name__ == '__main__': |
| 495 sys.exit(main()) | 516 sys.exit(main()) |
| OLD | NEW |